diff --git a/docs/.prettierignore b/docs/.prettierignore index 62cecd8a57..12ef0727eb 100644 --- a/docs/.prettierignore +++ b/docs/.prettierignore @@ -2,6 +2,3 @@ build html static - -# prettier interferes with the json response too much -src/developing/clients/jsonrpc-api.md diff --git a/docs/README.md b/docs/README.md index b28d3e44cd..e2c5ccd4c3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,11 +1,11 @@ -# Solana Docs Readme +# Solana Validator Docs Readme -Solana's Docs are built using [Docusaurus v2](https://v2.docusaurus.io/) with `npm`. +This validator's docs are built using [Docusaurus v2](https://v2.docusaurus.io/) with `npm`. Static content delivery is handled using `vercel`. ## Local Development -To set up the Solana Docs site locally: +To set up the Solana Validator Docs site locally: - install dependencies using `npm` - build locally via `./build.sh` @@ -30,7 +30,7 @@ The build script generates static content into the `build` directory and can be ./build.sh ``` -Running this build script requires **Docker**, and will auto fetch the [solanalabs/rust](https://hub.docker.com/r/solanalabs/rust) image from Docker hub to compile the desired version of the [Solana CLI](https://docs.solana.com/cli) from source. +Running this build script requires **Docker**, and will auto fetch the [solanalabs/rust](https://hub.docker.com/r/solanalabs/rust) image from Docker hub to compile the desired version of the [Solana CLI](https://docs.solanalabs.com/cli) from source. This build script will also: @@ -75,9 +75,9 @@ The docs are built and published in Travis CI with the `./build.sh` script. On e In each post-commit build, docs are built and published using `vercel` to their respective domain depending on the build branch. -- Master branch docs are published to `edge.docs.solana.com` -- Beta branch docs are published to `beta.docs.solana.com` -- Latest release tag docs are published to `docs.solana.com` +- Master branch docs are published to `edge.docs.solanalabs.com` +- Beta branch docs are published to `beta.docs.solanalabs.com` +- Latest release tag docs are published to `docs.solanalabs.com` ## Common Issues diff --git a/docs/build-cli-usage.sh b/docs/build-cli-usage.sh index ce5f582fa3..0917cb4737 100755 --- a/docs/build-cli-usage.sh +++ b/docs/build-cli-usage.sh @@ -15,7 +15,7 @@ out=${1:-src/cli/usage.md} # load the usage file's header cat src/cli/.usage.md.header > "$out" -# Skip generating the usage doc for non deployment commits of the docs +# Skip generating the detailed usage doc for non deployment commits of the docs if [[ -n $CI ]]; then if [[ $CI_BRANCH != $EDGE_CHANNEL* ]] && [[ $CI_BRANCH != $BETA_CHANNEL* ]] && [[ $CI_BRANCH != $STABLE_CHANNEL* ]]; then echo "**NOTE:** The usage doc is only auto-generated during full production deployments of the docs" diff --git a/docs/components/CodeDocBlock.jsx b/docs/components/CodeDocBlock.jsx deleted file mode 100644 index bd0099b99e..0000000000 --- a/docs/components/CodeDocBlock.jsx +++ /dev/null @@ -1,161 +0,0 @@ -import React from "react"; -import Link from "@docusaurus/Link"; -// import clsx from "clsx"; -import styles from "../src/pages/CodeDocBlock.module.css"; - -export function DocBlock({ children }) { - return
{children}
; -} - -export function DocSideBySide({ children }) { - return
{children}
; -} - -export function CodeParams({ children }) { - return
{children}
; -} - -export function CodeSnippets({ children }) { - return ( -
- {/*

Code Sample:

*/} - - {children} -
- ); -} - -/* - Display a single Parameter -*/ -export function Parameter(props) { - const { - name = null, - type = null, - required = null, - optional = null, - children, - } = computeHeader(props); - - return ( -
-

- {name && name} {type && type} {required && required}{" "} - {optional && optional} -

- - {children} -
- ); -} - -/* - Display a single Parameter's field data -*/ -export function Field(props) { - const { - name = null, - type = null, - values = null, - required = null, - defaultValue = null, - optional = null, - children, - } = computeHeader(props); - - return ( -
-

- {name && name} {type && type} {required && required}{" "} - {optional && optional} - {defaultValue && defaultValue} -

- -
- {values && values} - - {children} -
-
- ); -} - -/* - Parse an array of string values to display -*/ -export function Values({ values = null }) { - // format the Parameter's values - if (values && Array.isArray(values) && values?.length) { - values = values.map((value) => ( - - {value} - - )); - } - - return ( -

- Values: {values} -

- ); -} - -/* - Compute the formatted Parameter and Field component's header meta data -*/ -function computeHeader({ - name = null, - type = null, - href = null, - values = null, - required = null, - defaultValue = null, - optional = null, - children, -}) { - // format the Parameter's name - if (name) { - name = {name}; - - if (href) name = {name}; - } - - // format the Parameter's type - if (type) type = {type}; - - // format the Parameter's values - if (values && Array.isArray(values)) { - values = values.map((value) => ( - {value} - )); - } - - // format the `defaultValue` flag - if (defaultValue) { - defaultValue = ( - - Default: {defaultValue.toString()} - - ); - } - - // format the `required` flag - if (required) { - required = required; - } - // format the `optional` flag - else if (optional) { - optional = optional; - } - - return { - name, - type, - href, - values, - required, - defaultValue, - optional, - children, - }; -} diff --git a/docs/components/HomeCtaLinks.jsx b/docs/components/HomeCtaLinks.jsx index 6a7283425a..71d20014ad 100644 --- a/docs/components/HomeCtaLinks.jsx +++ b/docs/components/HomeCtaLinks.jsx @@ -6,7 +6,7 @@ export default function HomeCtaLinks() {
-
- {sidebarItems?.length > 0 && ( - - )} - -
{children}
-
- - ); -} -export default CardLayout; - -/* - Create a simple label based on the string of a doc file path -*/ -const computeLabel = (label) => { - label = label.split("/"); - label = label[label?.length - 1]?.replace("-", " "); - label = label.charAt(0).toUpperCase() + label.slice(1); - return label && label; -}; - -/* - Recursively parse the sidebar -*/ -const parseSidebar = (sidebarItems) => { - Object.keys(sidebarItems).forEach((key) => { - if (sidebarItems[key]?.type?.toLowerCase() === "category") { - sidebarItems[key].items = parseSidebar(sidebarItems[key].items); - } else sidebarItems[key] = formatter(sidebarItems[key]); - }); - return sidebarItems; -}; - -/* - Parser to format a sidebar item to be compatible with the `DocSidebar` component -*/ -const formatter = (item) => { - // handle string only document ids - if (typeof item === "string") { - item = { - type: "link", - href: item, - label: computeLabel(item) || item || "[unknown label]", - }; - } - - // handle object style docs - else if (item?.type?.toLowerCase() === "doc") { - item.type = "link"; - item.href = item.id; - item.label = item.label || computeLabel(item.href) || "[unknown label]"; - delete item.id; - } - - // fix for local routing that does not specify starting at the site root - if ( - !( - item?.href?.startsWith("/") || - item?.href?.startsWith("http:") || - item?.href?.startsWith("https") - ) - ) - item.href = `/${item?.href}`; - - return item; -}; diff --git a/docs/publish-docs.sh b/docs/publish-docs.sh index 0ae2d92716..28885d3b50 100755 --- a/docs/publish-docs.sh +++ b/docs/publish-docs.sh @@ -31,22 +31,125 @@ cat > "$CONFIG_FILE" < - -## getConfirmedBlock - -:::warning DEPRECATED -This method is expected to be removed in solana-core v2.0. -**Please use [getBlock](#getblock) instead** -::: - -Returns identity and transaction information about a confirmed block in the ledger - - - - - -### Parameters: - - - slot number, as u64 integer - - - - -Configuration object containing the following fields: - - - - - level of transaction detail to return, either "full", "signatures", or "none" - - - - whether to populate the `rewards` array. - - - - -Encoding format for Account data - - - -
- -- `jsonParsed` encoding attempts to use program-specific instruction parsers to return - more human-readable and explicit data in the `transaction.message.instructions` list. -- If `jsonParsed` is requested but a parser cannot be found, the instruction - falls back to regular JSON encoding (`accounts`, `data`, and `programIdIndex` fields). - -
- -
- -
- -### Result: - -The result field will be an object with the following fields: - -- `` - if specified block is not confirmed -- `` - if block is confirmed, an object with the following fields: - - `blockhash: ` - the blockhash of this block, as base-58 encoded string - - `previousBlockhash: ` - the blockhash of this block's parent, as base-58 encoded string; if the parent block is not available due to ledger cleanup, this field will return "11111111111111111111111111111111" - - `parentSlot: ` - the slot index of this block's parent - - `transactions: ` - present if "full" transaction details are requested; an array of JSON objects containing: - - `transaction: ` - [Transaction](#transaction-structure) object, either in JSON format or encoded binary data, depending on encoding parameter - - `meta: ` - transaction status metadata object, containing `null` or: - - `err: ` - Error if transaction failed, null if transaction succeeded. [TransactionError definitions](https://github.com/solana-labs/solana/blob/c0c60386544ec9a9ec7119229f37386d9f070523/sdk/src/transaction/error.rs#L13) - - `fee: ` - fee this transaction was charged, as u64 integer - - `preBalances: ` - array of u64 account balances from before the transaction was processed - - `postBalances: ` - array of u64 account balances after the transaction was processed - - `innerInstructions: ` - List of [inner instructions](#inner-instructions-structure) or `null` if inner instruction recording was not enabled during this transaction - - `preTokenBalances: ` - List of [token balances](#token-balances-structure) from before the transaction was processed or omitted if token balance recording was not yet enabled during this transaction - - `postTokenBalances: ` - List of [token balances](#token-balances-structure) from after the transaction was processed or omitted if token balance recording was not yet enabled during this transaction - - `logMessages: ` - array of string log messages or `null` if log message recording was not enabled during this transaction - - DEPRECATED: `status: ` - Transaction status - - `"Ok": ` - Transaction was successful - - `"Err": ` - Transaction failed with TransactionError - - `signatures: ` - present if "signatures" are requested for transaction details; an array of signatures strings, corresponding to the transaction order in the block - - `rewards: ` - present if rewards are requested; an array of JSON objects containing: - - `pubkey: ` - The public key, as base-58 encoded string, of the account that received the reward - - `lamports: `- number of reward lamports credited or debited by the account, as a i64 - - `postBalance: ` - account balance in lamports after the reward was applied - - `rewardType: ` - type of reward: "fee", "rent", "voting", "staking" - - `commission: ` - vote account commission when the reward was credited, only present for voting and staking rewards - - `blockTime: ` - estimated production time, as Unix timestamp (seconds since the Unix epoch). null if not available - -#### For more details on returned data: - -- [Transaction Structure](#transaction-structure) -- [Inner Instructions Structure](#inner-instructions-structure) -- [Token Balances Structure](#token-balances-structure) - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", "id": 1, - "method": "getConfirmedBlock", - "params": [430, "base64"] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "blockTime": null, - "blockhash": "3Eq21vXNB5s86c62bVuUfTeaMif1N2kUqRPBmGRJhyTA", - "parentSlot": 429, - "previousBlockhash": "mfcyqEXB3DnHXki6KjjmZck6YjmZLvpAByy2fj4nh6B", - "rewards": [], - "transactions": [ - { - "meta": { - "err": null, - "fee": 5000, - "innerInstructions": [], - "logMessages": [], - "postBalances": [499998932500, 26858640, 1, 1, 1], - "postTokenBalances": [], - "preBalances": [499998937500, 26858640, 1, 1, 1], - "preTokenBalances": [], - "status": { - "Ok": null - } - }, - "transaction": [ - "AVj7dxHlQ9IrvdYVIjuiRFs1jLaDMHixgrv+qtHBwz51L4/ImLZhszwiyEJDIp7xeBSpm/TX5B7mYzxa+fPOMw0BAAMFJMJVqLw+hJYheizSoYlLm53KzgT82cDVmazarqQKG2GQsLgiqktA+a+FDR4/7xnDX7rsusMwryYVUdixfz1B1Qan1RcZLwqvxvJl4/t3zHragsUp0L47E24tAFUgAAAABqfVFxjHdMkoVmOYaR1etoteuKObS21cc1VbIQAAAAAHYUgdNXR0u3xNdiTr072z2DVec9EQQ/wNo1OAAAAAAAtxOUhPBp2WSjUNJEgfvy70BbxI00fZyEPvFHNfxrtEAQQEAQIDADUCAAAAAQAAAAAAAACtAQAAAAAAAAdUE18R96XTJCe+YfRfUp6WP+YKCy/72ucOL8AoBFSpAA==", - "base64" - ] - } - ] - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/deprecated/_getConfirmedBlocks.mdx b/docs/src/api/deprecated/_getConfirmedBlocks.mdx deleted file mode 100644 index 5a6b21c12a..0000000000 --- a/docs/src/api/deprecated/_getConfirmedBlocks.mdx +++ /dev/null @@ -1,71 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getConfirmedBlocks - -:::warning DEPRECATED -This method is expected to be removed in solana-core v2.0 -**Please use [getBlocks](#getblocks) instead** -::: - -Returns a list of confirmed blocks between two slots - - - - - -### Parameters: - - - start_slot, as u64 integer - - - - -Configuration object containing the following fields: - - - - - -### Result: - -The result field will be an array of u64 integers listing confirmed blocks -between `start_slot` and either `end_slot` - if provided, or latest confirmed block, -inclusive. Max range allowed is 500,000 slots. - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc": "2.0","id":1,"method":"getConfirmedBlocks","params":[5, 10]} -' -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": [5, 6, 7, 8, 9, 10], "id": 1 } -``` - - - - diff --git a/docs/src/api/deprecated/_getConfirmedBlocksWithLimit.mdx b/docs/src/api/deprecated/_getConfirmedBlocksWithLimit.mdx deleted file mode 100644 index 3daec0abc2..0000000000 --- a/docs/src/api/deprecated/_getConfirmedBlocksWithLimit.mdx +++ /dev/null @@ -1,78 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getConfirmedBlocksWithLimit - -:::warning DEPRECATED -This method is expected to be removed in solana-core v2.0 -**Please use [getBlocksWithLimit](#getblockswithlimit) instead** -::: - -Returns a list of confirmed blocks starting at the given slot - - - - - -### Parameters: - - - start_slot, as u64 integer - - - - limit, as u64 integer - - - - -Configuration object containing the following fields: - - - - - -### Result: - -The result field will be an array of u64 integers listing confirmed blocks -starting at `start_slot` for up to `limit` blocks, inclusive. - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", "id": 1, - "method": "getConfirmedBlocksWithLimit", - "params": [5, 3] - } -' -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": [5, 6, 7], "id": 1 } -``` - - - - diff --git a/docs/src/api/deprecated/_getConfirmedSignaturesForAddress2.mdx b/docs/src/api/deprecated/_getConfirmedSignaturesForAddress2.mdx deleted file mode 100644 index 7d8c803d06..0000000000 --- a/docs/src/api/deprecated/_getConfirmedSignaturesForAddress2.mdx +++ /dev/null @@ -1,114 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getConfirmedSignaturesForAddress2 - -:::warning DEPRECATED -This method is expected to be removed in solana-core v2.0 -**Please use [getSignaturesForAddress](#getsignaturesforaddress) instead** -::: - -Returns signatures for confirmed transactions that include the given address in -their `accountKeys` list. Returns signatures backwards in time from the -provided signature or most recent confirmed block - - - - - -### Parameters: - - - account address, as base-58 encoded string - - - -Configuration object containing the following fields: - - - - - maximum transaction signatures to return (between 1 and 1,000, default: - 1,000). - - - - start searching backwards from this transaction signature. (If not provided - the search starts from the top of the highest max confirmed block.) - - - - search until this transaction signature, if found before limit reached. - - - - -### Result: - -The result field will be an array of ``, ordered -from newest to oldest transaction, containing transaction signature information with the following fields: - -- `signature: ` - transaction signature as base-58 encoded string -- `slot: ` - The slot that contains the block with the transaction -- `err: ` - Error if transaction failed, null if transaction succeeded. [TransactionError definitions](https://github.com/solana-labs/solana/blob/c0c60386544ec9a9ec7119229f37386d9f070523/sdk/src/transaction/error.rs#L13) -- `memo: ` - Memo associated with the transaction, null if no memo is present -- `blockTime: ` - estimated production time, as Unix timestamp (seconds since the Unix epoch) of when transaction was processed. null if not available. - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getConfirmedSignaturesForAddress2", - "params": [ - "Vote111111111111111111111111111111111111111", - { - "limit": 1 - } - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": [ - { - "err": null, - "memo": null, - "signature": "5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv", - "slot": 114, - "blockTime": null - } - ], - "id": 1 -} -``` - - - - diff --git a/docs/src/api/deprecated/_getConfirmedTransaction.mdx b/docs/src/api/deprecated/_getConfirmedTransaction.mdx deleted file mode 100644 index 9586975df6..0000000000 --- a/docs/src/api/deprecated/_getConfirmedTransaction.mdx +++ /dev/null @@ -1,133 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getConfirmedTransaction - -:::warning DEPRECATED -This method is expected to be removed in solana-core v2.0 -**Please use [getTransaction](#gettransaction) instead** -::: - -Returns transaction details for a confirmed transaction - - - - - -### Parameters: - - - transaction signature, as base-58 encoded string - - - - -Configuration object containing the following fields: - - - - - -Encoding format for Account data - - - -
- -- `base58` is slow and limited to less than 129 bytes of Account data. -- `jsonParsed` encoding attempts to use program-specific instruction parsers - to return more human-readable and explicit data in the `transaction.message.instructions` list. -- If `jsonParsed` is requested but a parser cannot be found, the instruction - falls back to regular `json` encoding (`accounts`, `data`, and `programIdIndex` fields). - -
- -
- -
- -### Result: - -- `` - if transaction is not found or not confirmed -- `` - if transaction is confirmed, an object with the following fields: - - `slot: ` - the slot this transaction was processed in - - `transaction: ` - [Transaction](#transaction-structure) object, either in JSON format or encoded binary data, depending on encoding parameter - - `blockTime: ` - estimated production time, as Unix timestamp (seconds since the Unix epoch) of when the transaction was processed. null if not available - - `meta: ` - transaction status metadata object: - - `err: ` - Error if transaction failed, null if transaction succeeded. [TransactionError definitions](https://docs.rs/solana-sdk/VERSION_FOR_DOCS_RS/solana_sdk/transaction/enum.TransactionError.html) - - `fee: ` - fee this transaction was charged, as u64 integer - - `preBalances: ` - array of u64 account balances from before the transaction was processed - - `postBalances: ` - array of u64 account balances after the transaction was processed - - `innerInstructions: ` - List of [inner instructions](#inner-instructions-structure) or `null` if inner instruction recording was not enabled during this transaction - - `preTokenBalances: ` - List of [token balances](#token-balances-structure) from before the transaction was processed or omitted if token balance recording was not yet enabled during this transaction - - `postTokenBalances: ` - List of [token balances](#token-balances-structure) from after the transaction was processed or omitted if token balance recording was not yet enabled during this transaction - - `logMessages: ` - array of string log messages or `null` if log message recording was not enabled during this transaction - - DEPRECATED: `status: ` - Transaction status - - `"Ok": ` - Transaction was successful - - `"Err": ` - Transaction failed with TransactionError - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getConfirmedTransaction", - "params": [ - "2nBhEBYYvfaAe16UMNqRHre4YNSskvuYgx3M6E4JP1oDYvZEJHvoPzyUidNgNX5r9sTyN1J9UxtbCXy2rqYcuyuv", - "base64" - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "meta": { - "err": null, - "fee": 5000, - "innerInstructions": [], - "postBalances": [499998932500, 26858640, 1, 1, 1], - "postTokenBalances": [], - "preBalances": [499998937500, 26858640, 1, 1, 1], - "preTokenBalances": [], - "status": { - "Ok": null - } - }, - "slot": 430, - "transaction": [ - "AVj7dxHlQ9IrvdYVIjuiRFs1jLaDMHixgrv+qtHBwz51L4/ImLZhszwiyEJDIp7xeBSpm/TX5B7mYzxa+fPOMw0BAAMFJMJVqLw+hJYheizSoYlLm53KzgT82cDVmazarqQKG2GQsLgiqktA+a+FDR4/7xnDX7rsusMwryYVUdixfz1B1Qan1RcZLwqvxvJl4/t3zHragsUp0L47E24tAFUgAAAABqfVFxjHdMkoVmOYaR1etoteuKObS21cc1VbIQAAAAAHYUgdNXR0u3xNdiTr072z2DVec9EQQ/wNo1OAAAAAAAtxOUhPBp2WSjUNJEgfvy70BbxI00fZyEPvFHNfxrtEAQQEAQIDADUCAAAAAQAAAAAAAACtAQAAAAAAAAdUE18R96XTJCe+YfRfUp6WP+YKCy/72ucOL8AoBFSpAA==", - "base64" - ] - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/deprecated/_getFeeCalculatorForBlockhash.mdx b/docs/src/api/deprecated/_getFeeCalculatorForBlockhash.mdx deleted file mode 100644 index 66b0d954ee..0000000000 --- a/docs/src/api/deprecated/_getFeeCalculatorForBlockhash.mdx +++ /dev/null @@ -1,97 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getFeeCalculatorForBlockhash - -:::warning DEPRECATED -This method is expected to be removed in solana-core v2.0 -**Please use [isBlockhashValid](#isblockhashvalid) or [getFeeForMessage](#getfeeformessage) instead** -::: - -Returns the fee calculator associated with the query blockhash, or `null` if the blockhash has expired - - - - - -### Parameters: - - - query blockhash, as a base-58 encoded string - - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - -### Result: - -The result will be an RpcResponse JSON object with `value` equal to: - -- `` - if the query blockhash has expired; or -- `` - otherwise, a JSON object containing: - - `feeCalculator: ` - `FeeCalculator` object describing the cluster fee rate at the queried blockhash - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getFeeCalculatorForBlockhash", - "params": [ - "GJxqhuxcgfn5Tcj6y3f8X4FeCDd2RQ6SnEMo1AAxrPRZ" - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 221 - }, - "value": { - "feeCalculator": { - "lamportsPerSignature": 5000 - } - } - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/deprecated/_getFeeRateGovernor.mdx b/docs/src/api/deprecated/_getFeeRateGovernor.mdx deleted file mode 100644 index e7b87cda19..0000000000 --- a/docs/src/api/deprecated/_getFeeRateGovernor.mdx +++ /dev/null @@ -1,76 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getFeeRateGovernor - -:::warning DEPRECATED -This method is expected to be removed in solana-core v2.0 -::: - -Returns the fee rate governor information from the root bank - - - - - -### Parameters: - -**None** - -### Result: - -The result will be an RpcResponse JSON object with `value` equal to an `object` with the following fields: - -- `burnPercent: ` - Percentage of fees collected to be destroyed -- `maxLamportsPerSignature: ` - Largest value `lamportsPerSignature` can attain for the next slot -- `minLamportsPerSignature: ` - Smallest value `lamportsPerSignature` can attain for the next slot -- `targetLamportsPerSignature: ` - Desired fee rate for the cluster -- `targetSignaturesPerSlot: ` - Desired signature rate for the cluster - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getFeeRateGovernor"} -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 54 - }, - "value": { - "feeRateGovernor": { - "burnPercent": 50, - "maxLamportsPerSignature": 100000, - "minLamportsPerSignature": 5000, - "targetLamportsPerSignature": 10000, - "targetSignaturesPerSlot": 20000 - } - } - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/deprecated/_getFees.mdx b/docs/src/api/deprecated/_getFees.mdx deleted file mode 100644 index 62cd337454..0000000000 --- a/docs/src/api/deprecated/_getFees.mdx +++ /dev/null @@ -1,92 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getFees - -:::warning DEPRECATED -This method is expected to be removed in solana-core v2.0 -**Please use [getFeeForMessage](#getfeeformessage) instead** -::: - -Returns a recent block hash from the ledger, a fee schedule that can be used to -compute the cost of submitting a transaction using it, and the last slot in -which the blockhash will be valid. - - - - - -### Parameters: - - - Pubkey of account to query, as base-58 encoded string - - - - -Configuration object containing the following fields: - - - - - -### Result: - -The result will be an RpcResponse JSON object with `value` set to a JSON object with the following fields: - -- `blockhash: ` - a Hash as base-58 encoded string -- `feeCalculator: ` - FeeCalculator object, the fee schedule for this block hash -- `lastValidSlot: ` - DEPRECATED - this value is inaccurate and should not be relied upon -- `lastValidBlockHeight: ` - last [block height](../../terminology.md#block-height) at which the blockhash will be valid - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { "jsonrpc":"2.0", "id": 1, "method":"getFees"} -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 1 - }, - "value": { - "blockhash": "CSymwgTNX1j3E4qhKfJAUE41nBWEwXufoYryPbkde5RR", - "feeCalculator": { - "lamportsPerSignature": 5000 - }, - "lastValidSlot": 297, - "lastValidBlockHeight": 296 - } - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/deprecated/_getRecentBlockhash.mdx b/docs/src/api/deprecated/_getRecentBlockhash.mdx deleted file mode 100644 index 456685c3dd..0000000000 --- a/docs/src/api/deprecated/_getRecentBlockhash.mdx +++ /dev/null @@ -1,87 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getRecentBlockhash - -:::warning DEPRECATED -This method is expected to be removed in solana-core v2.0 -**Please use [getLatestBlockhash](#getlatestblockhash) instead** -::: - -Returns a recent block hash from the ledger, and a fee schedule that can be used to compute the cost of submitting a transaction using it. - - - - - -### Parameters: - - - Pubkey of account to query, as base-58 encoded string - - - - -Configuration object containing the following fields: - - - - - -### Result: - -An RpcResponse containing a JSON object consisting of a string blockhash and FeeCalculator JSON object. - -- `RpcResponse` - RpcResponse JSON object with `value` field set to a JSON object including: -- `blockhash: ` - a Hash as base-58 encoded string -- `feeCalculator: ` - FeeCalculator object, the fee schedule for this block hash - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getRecentBlockhash"} -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 1 - }, - "value": { - "blockhash": "CSymwgTNX1j3E4qhKfJAUE41nBWEwXufoYryPbkde5RR", - "feeCalculator": { - "lamportsPerSignature": 5000 - } - } - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/deprecated/_getSnapshotSlot.mdx b/docs/src/api/deprecated/_getSnapshotSlot.mdx deleted file mode 100644 index 42ee186d5c..0000000000 --- a/docs/src/api/deprecated/_getSnapshotSlot.mdx +++ /dev/null @@ -1,64 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getSnapshotSlot - -:::warning DEPRECATED -This method is expected to be removed in solana-core v2.0 -**Please use [getHighestSnapshotSlot](#gethighestsnapshotslot) instead** -::: - -Returns the highest slot that the node has a snapshot for - - - - - -### Parameters: - -**None** - -### Result: - -`` - Snapshot slot - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getSnapshotSlot"} -' -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 100, "id": 1 } -``` - -Result when the node has no snapshot: - -```json -{ - "jsonrpc": "2.0", - "error": { "code": -32008, "message": "No snapshot" }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/http.md b/docs/src/api/http.md deleted file mode 100644 index 9edf2c792c..0000000000 --- a/docs/src/api/http.md +++ /dev/null @@ -1,417 +0,0 @@ ---- -title: JSON RPC HTTP Methods -displayed_sidebar: apiHttpMethodsSidebar -hide_table_of_contents: true ---- - -Solana nodes accept HTTP requests using the [JSON-RPC 2.0](https://www.jsonrpc.org/specification) specification. - -:::info -For JavaScript applications, use the [@solana/web3.js](https://github.com/solana-labs/solana-web3.js) library as a convenient interface for the RPC methods to interact with a Solana node. - -For an PubSub connection to a Solana node, use the [Websocket API](./websocket.md). -::: - -## RPC HTTP Endpoint - -**Default port:** 8899 e.g. [http://localhost:8899](http://localhost:8899), [http://192.168.1.88:8899](http://192.168.1.88:8899) - -## Request Formatting - -To make a JSON-RPC request, send an HTTP POST request with a `Content-Type: application/json` header. The JSON request data should contain 4 fields: - -- `jsonrpc: ` - set to `"2.0"` -- `id: ` - a unique client-generated identifying integer -- `method: ` - a string containing the method to be invoked -- `params: ` - a JSON array of ordered parameter values - -Example using curl: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getBalance", - "params": [ - "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri" - ] - } -' -``` - -The response output will be a JSON object with the following fields: - -- `jsonrpc: ` - matching the request specification -- `id: ` - matching the request identifier -- `result: ` - requested data or success confirmation - -Requests can be sent in batches by sending an array of JSON-RPC request objects as the data for a single POST. - -## Definitions - -- Hash: A SHA-256 hash of a chunk of data. -- Pubkey: The public key of a Ed25519 key-pair. -- Transaction: A list of Solana instructions signed by a client keypair to authorize those actions. -- Signature: An Ed25519 signature of transaction's payload data including instructions. This can be used to identify transactions. - -## Configuring State Commitment - -For preflight checks and transaction processing, Solana nodes choose which bank -state to query based on a commitment requirement set by the client. The -commitment describes how finalized a block is at that point in time. When -querying the ledger state, it's recommended to use lower levels of commitment -to report progress and higher levels to ensure the state will not be rolled back. - -In descending order of commitment (most finalized to least finalized), clients -may specify: - -- `"finalized"` - the node will query the most recent block confirmed by supermajority - of the cluster as having reached maximum lockout, meaning the cluster has - recognized this block as finalized -- `"confirmed"` - the node will query the most recent block that has been voted on by supermajority of the cluster. - - It incorporates votes from gossip and replay. - - It does not count votes on descendants of a block, only direct votes on that block. - - This confirmation level also upholds "optimistic confirmation" guarantees in - release 1.3 and onwards. -- `"processed"` - the node will query its most recent block. Note that the block - may still be skipped by the cluster. - -For processing many dependent transactions in series, it's recommended to use -`"confirmed"` commitment, which balances speed with rollback safety. -For total safety, it's recommended to use`"finalized"` commitment. - -#### Example - -The commitment parameter should be included as the last element in the `params` array: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getBalance", - "params": [ - "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri", - { - "commitment": "finalized" - } - ] - } -' -``` - -#### Default: - -If commitment configuration is not provided, the node will default to `"finalized"` commitment - -Only methods that query bank state accept the commitment parameter. They are indicated in the API Reference below. - -#### RpcResponse Structure - -Many methods that take a commitment parameter return an RpcResponse JSON object comprised of two parts: - -- `context` : An RpcResponseContext JSON structure including a `slot` field at which the operation was evaluated. -- `value` : The value returned by the operation itself. - -#### Parsed Responses - -Some methods support an `encoding` parameter, and can return account or -instruction data in parsed JSON format if `"encoding":"jsonParsed"` is requested -and the node has a parser for the owning program. Solana nodes currently support -JSON parsing for the following native and SPL programs: - -| Program | Account State | Instructions | -| ---------------------------- | ------------- | ------------ | -| Address Lookup | v1.15.0 | v1.15.0 | -| BPF Loader | n/a | stable | -| BPF Upgradeable Loader | stable | stable | -| Config | stable | | -| SPL Associated Token Account | n/a | stable | -| SPL Memo | n/a | stable | -| SPL Token | stable | stable | -| SPL Token 2022 | stable | stable | -| Stake | stable | stable | -| Vote | stable | stable | - -The list of account parsers can be found [here](https://github.com/solana-labs/solana/blob/master/account-decoder/src/parse_account_data.rs), and instruction parsers [here](https://github.com/solana-labs/solana/blob/master/transaction-status/src/parse_instruction.rs). - -## Filter criteria - -Some methods support providing a `filters` object to enable pre-filtering the data returned within the RpcResponse JSON object. The following filters exist: - -- `memcmp: object` - compares a provided series of bytes with program account data at a particular offset. Fields: - - - `offset: usize` - offset into program account data to start comparison - - `bytes: string` - data to match, as encoded string - - `encoding: string` - encoding for filter `bytes` data, either "base58" or "base64". Data is limited in size to 128 or fewer decoded bytes.
- **NEW: This field, and base64 support generally, is only available in solana-core v1.14.0 or newer. Please omit when querying nodes on earlier versions** - -- `dataSize: u64` - compares the program account data length with the provided data size - -## Health Check - -Although not a JSON RPC API, a `GET /health` at the RPC HTTP Endpoint provides a -health-check mechanism for use by load balancers or other network -infrastructure. This request will always return a HTTP 200 OK response with a body of -"ok", "behind" or "unknown": - -- `ok`: The node is within `HEALTH_CHECK_SLOT_DISTANCE` slots from the latest cluster confirmed slot -- `behind { distance }`: The node is behind `distance` slots from the latest cluster confirmed slot where `distance > HEALTH_CHECK_SLOT_DISTANCE` -- `unknown`: The node is unable to determine where it stands in relation to the cluster - -## JSON RPC API Reference - -import GetAccountInfo from "./methods/\_getAccountInfo.mdx" - - - -import GetBalance from "./methods/\_getBalance.mdx" - - - -import GetBlock from "./methods/\_getBlock.mdx" - - - -import GetBlockHeight from "./methods/\_getBlockHeight.mdx" - - - -import GetBlockProduction from "./methods/\_getBlockProduction.mdx" - - - -import GetBlockCommitment from "./methods/\_getBlockCommitment.mdx" - - - -import GetBlocks from "./methods/\_getBlocks.mdx" - - - -import GetBlocksWithLimit from "./methods/\_getBlocksWithLimit.mdx" - - - -import GetBlockTime from "./methods/\_getBlockTime.mdx" - - - -import GetClusterNodes from "./methods/\_getClusterNodes.mdx" - - - -import GetEpochInfo from "./methods/\_getEpochInfo.mdx" - - - -import GetEpochSchedule from "./methods/\_getEpochSchedule.mdx" - - - -import GetFeeForMessage from "./methods/\_getFeeForMessage.mdx" - - - -import GetFirstAvailableBlock from "./methods/\_getFirstAvailableBlock.mdx" - - - -import GetGenesisHash from "./methods/\_getGenesisHash.mdx" - - - -import GetHealth from "./methods/\_getHealth.mdx" - - - -import GetHighestSnapshotSlot from "./methods/\_getHighestSnapshotSlot.mdx" - - - -import GetIdentity from "./methods/\_getIdentity.mdx" - - - -import GetInflationGovernor from "./methods/\_getInflationGovernor.mdx" - - - -import GetInflationRate from "./methods/\_getInflationRate.mdx" - - - -import GetInflationReward from "./methods/\_getInflationReward.mdx" - - - -import GetLargestAccounts from "./methods/\_getLargestAccounts.mdx" - - - -import GetLatestBlockhash from "./methods/\_getLatestBlockhash.mdx" - - - -import GetLeaderSchedule from "./methods/\_getLeaderSchedule.mdx" - - - -import GetMaxRetransmitSlot from "./methods/\_getMaxRetransmitSlot.mdx" - - - -import GetMaxShredInsertSlot from "./methods/\_getMaxShredInsertSlot.mdx" - - - -import GetMinimumBalanceForRentExemption from "./methods/\_getMinimumBalanceForRentExemption.mdx" - - - -import GetMultipleAccounts from "./methods/\_getMultipleAccounts.mdx" - - - -import GetProgramAccounts from "./methods/\_getProgramAccounts.mdx" - - - -import GetRecentPerformanceSamples from "./methods/\_getRecentPerformanceSamples.mdx" - - - -import GetRecentPrioritizationFees from "./methods/\_getRecentPrioritizationFees.mdx" - - - -import GetSignaturesForAddress from "./methods/\_getSignaturesForAddress.mdx" - - - -import GetSignatureStatuses from "./methods/\_getSignatureStatuses.mdx" - - - -import GetSlot from "./methods/\_getSlot.mdx" - - - -import GetSlotLeader from "./methods/\_getSlotLeader.mdx" - - - -import GetSlotLeaders from "./methods/\_getSlotLeaders.mdx" - - - -import GetStakeActivation from "./methods/\_getStakeActivation.mdx" - - - -import GetStakeMinimumDelegation from "./methods/\_getStakeMinimumDelegation.mdx" - - - -import GetSupply from "./methods/\_getSupply.mdx" - - - -import GetTokenAccountBalance from "./methods/\_getTokenAccountBalance.mdx" - - - -import GetTokenAccountsByDelegate from "./methods/\_getTokenAccountsByDelegate.mdx" - - - -import GetTokenAccountsByOwner from "./methods/\_getTokenAccountsByOwner.mdx" - - - -import GetTokenLargestAccounts from "./methods/\_getTokenLargestAccounts.mdx" - - - -import GetTokenSupply from "./methods/\_getTokenSupply.mdx" - - - -import GetTransaction from "./methods/\_getTransaction.mdx" - - - -import GetTransactionCount from "./methods/\_getTransactionCount.mdx" - - - -import GetVersion from "./methods/\_getVersion.mdx" - - - -import GetVoteAccounts from "./methods/\_getVoteAccounts.mdx" - - - -import IsBlockhashValid from "./methods/\_isBlockhashValid.mdx" - - - -import MinimumLedgerSlot from "./methods/\_minimumLedgerSlot.mdx" - - - -import RequestAirdrop from "./methods/\_requestAirdrop.mdx" - - - -import SendTransaction from "./methods/\_sendTransaction.mdx" - - - -import SimulateTransaction from "./methods/\_simulateTransaction.mdx" - - - -## JSON RPC API Deprecated Methods - -import GetConfirmedBlock from "./deprecated/\_getConfirmedBlock.mdx" - - - -import GetConfirmedBlocks from "./deprecated/\_getConfirmedBlocks.mdx" - - - -import GetConfirmedBlocksWithLimit from "./deprecated/\_getConfirmedBlocksWithLimit.mdx" - - - -import GetConfirmedSignaturesForAddress2 from "./deprecated/\_getConfirmedSignaturesForAddress2.mdx" - - - -import GetConfirmedTransaction from "./deprecated/\_getConfirmedTransaction.mdx" - - - -import GetFeeCalculatorForBlockhash from "./deprecated/\_getFeeCalculatorForBlockhash.mdx" - - - -import GetFeeRateGovernor from "./deprecated/\_getFeeRateGovernor.mdx" - - - -import GetFees from "./deprecated/\_getFees.mdx" - - - -import GetRecentBlockhash from "./deprecated/\_getRecentBlockhash.mdx" - - - -import GetSnapshotSlot from "./deprecated/\_getSnapshotSlot.mdx" - - diff --git a/docs/src/api/methods/_getAccountInfo.mdx b/docs/src/api/methods/_getAccountInfo.mdx deleted file mode 100644 index 35e55f0a78..0000000000 --- a/docs/src/api/methods/_getAccountInfo.mdx +++ /dev/null @@ -1,138 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getAccountInfo - -Returns all information associated with the account of provided Pubkey - - - - - -### Parameters: - - - Pubkey of account to query, as base-58 encoded string - - - - -Configuration object containing the following fields: - - - - - -Encoding format for Account data - - - -
- -- `base58` is slow and limited to less than 129 bytes of Account data. -- `base64` will return base64 encoded data for Account data of any size. -- `base64+zstd` compresses the Account data using [Zstandard](https://facebook.github.io/zstd/) - and base64-encodes the result. -- `jsonParsed` encoding attempts to use program-specific state parsers to return - more human-readable and explicit account state data. -- If `jsonParsed` is requested but a parser cannot be found, the field falls - back to `base64` encoding, detectable when the `data` field is type `string`. - -
- -
- - - Request a slice of the account's data. - - - `length: ` - number of bytes to return - - `offset: ` - byte offset from which to start reading - -:::info -Data slicing is only available for base58, base64, or base64+zstd encodings. -::: - - - - The minimum slot that the request can be evaluated at - - -
- -### Result: - -The result will be an RpcResponse JSON object with `value` equal to: - -- `` - if the requested account doesn't exist -- `` - otherwise, a JSON object containing: - - `lamports: ` - number of lamports assigned to this account, as a u64 - - `owner: ` - base-58 encoded Pubkey of the program this account has been assigned to - - `data: <[string, encoding]|object>` - data associated with the account, either as encoded binary data or JSON format `{: }` - depending on encoding parameter - - `executable: ` - boolean indicating if the account contains a program \(and is strictly read-only\) - - `rentEpoch: ` - the epoch at which this account will next owe rent, as u64 - - `size: ` - the data size of the account - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getAccountInfo", - "params": [ - "vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg", - { - "encoding": "base58" - } - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 1 - }, - "value": { - "data": [ - "11116bv5nS2h3y12kD1yUKeMZvGcKLSjQgX6BeV7u1FrjeJcKfsHRTPuR3oZ1EioKtYGiYxpxMG5vpbZLsbcBYBEmZZcMKaSoGx9JZeAuWf", - "base58" - ], - "executable": false, - "lamports": 1000000000, - "owner": "11111111111111111111111111111111", - "rentEpoch": 2, - "space": 80 - } - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getBalance.mdx b/docs/src/api/methods/_getBalance.mdx deleted file mode 100644 index 0cd0f0c6d0..0000000000 --- a/docs/src/api/methods/_getBalance.mdx +++ /dev/null @@ -1,78 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getBalance - -Returns the balance of the account of provided Pubkey - - - - - -### Parameters: - - - Pubkey of account to query, as base-58 encoded string - - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - -### Result: - -`RpcResponse` - RpcResponse JSON object with `value` field set to the balance - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", "id": 1, - "method": "getBalance", - "params": [ - "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri" - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { "context": { "slot": 1 }, "value": 0 }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getBlock.mdx b/docs/src/api/methods/_getBlock.mdx deleted file mode 100644 index 6ced795c2e..0000000000 --- a/docs/src/api/methods/_getBlock.mdx +++ /dev/null @@ -1,288 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getBlock - -Returns identity and transaction information about a confirmed block in the ledger - - - - - -### Parameters: - - - slot number, as u64 integer - - - - -Configuration object containing the following fields: - - -
  • - the default is finalized -
  • -
  • - processed is not supported. -
  • -
    - - - -encoding format for each returned Transaction - - - -
    - -- `jsonParsed` attempts to use program-specific instruction parsers to return - more human-readable and explicit data in the `transaction.message.instructions` list. -- If `jsonParsed` is requested but a parser cannot be found, the instruction - falls back to regular JSON encoding (`accounts`, `data`, and `programIdIndex` fields). - -
    - -
    - - - -level of transaction detail to return - - - -
    - -- If `accounts` are requested, transaction details only include signatures and - an annotated list of accounts in each transaction. -- Transaction metadata is limited to only: fee, err, pre_balances, - post_balances, pre_token_balances, and post_token_balances. - -
    - -
    - - - -the max transaction version to return in responses. - -
    - -- If the requested block contains a transaction with a higher version, an - error will be returned. -- If this parameter is omitted, only legacy transactions will be returned, and - a block containing any versioned transaction will prompt the error. - -
    - -
    - - - whether to populate the `rewards` array. If parameter not provided, the - default includes rewards. - - -
    - -### Result: - -The result field will be an object with the following fields: - -- `` - if specified block is not confirmed -- `` - if block is confirmed, an object with the following fields: - - `blockhash: ` - the blockhash of this block, as base-58 encoded string - - `previousBlockhash: ` - the blockhash of this block's parent, as base-58 encoded string; if the parent block is not available due to ledger cleanup, this field will return "11111111111111111111111111111111" - - `parentSlot: ` - the slot index of this block's parent - - `transactions: ` - present if "full" transaction details are requested; an array of JSON objects containing: - - `transaction: ` - [Transaction](#transaction-structure) object, either in JSON format or encoded binary data, depending on encoding parameter - - `meta: ` - transaction status metadata object, containing `null` or: - - `err: ` - Error if transaction failed, null if transaction succeeded. [TransactionError definitions](https://github.com/solana-labs/solana/blob/c0c60386544ec9a9ec7119229f37386d9f070523/sdk/src/transaction/error.rs#L13) - - `fee: ` - fee this transaction was charged, as u64 integer - - `preBalances: ` - array of u64 account balances from before the transaction was processed - - `postBalances: ` - array of u64 account balances after the transaction was processed - - `innerInstructions: ` - List of [inner instructions](#inner-instructions-structure) or `null` if inner instruction recording was not enabled during this transaction - - `preTokenBalances: ` - List of [token balances](#token-balances-structure) from before the transaction was processed or omitted if token balance recording was not yet enabled during this transaction - - `postTokenBalances: ` - List of [token balances](#token-balances-structure) from after the transaction was processed or omitted if token balance recording was not yet enabled during this transaction - - `logMessages: ` - array of string log messages or `null` if log message recording was not enabled during this transaction - - `rewards: ` - transaction-level rewards, populated if rewards are requested; an array of JSON objects containing: - - `pubkey: ` - The public key, as base-58 encoded string, of the account that received the reward - - `lamports: `- number of reward lamports credited or debited by the account, as a i64 - - `postBalance: ` - account balance in lamports after the reward was applied - - `rewardType: ` - type of reward: "fee", "rent", "voting", "staking" - - `commission: ` - vote account commission when the reward was credited, only present for voting and staking rewards - - DEPRECATED: `status: ` - Transaction status - - `"Ok": ` - Transaction was successful - - `"Err": ` - Transaction failed with TransactionError - - `loadedAddresses: ` - Transaction addresses loaded from address lookup tables. Undefined if `maxSupportedTransactionVersion` is not set in request params, or if `jsonParsed` encoding is set in request params. - - `writable: ` - Ordered list of base-58 encoded addresses for writable loaded accounts - - `readonly: ` - Ordered list of base-58 encoded addresses for readonly loaded accounts - - `returnData: ` - the most-recent return data generated by an instruction in the transaction, with the following fields: - - `programId: ` - the program that generated the return data, as base-58 encoded Pubkey - - `data: <[string, encoding]>` - the return data itself, as base-64 encoded binary data - - `computeUnitsConsumed: ` - number of [compute units](developing/programming-model/runtime.md#compute-budget) consumed by the transaction - - `version: <"legacy"|number|undefined>` - Transaction version. Undefined if `maxSupportedTransactionVersion` is not set in request params. - - `signatures: ` - present if "signatures" are requested for transaction details; an array of signatures strings, corresponding to the transaction order in the block - - `rewards: ` - block-level rewards, present if rewards are requested; an array of JSON objects containing: - - `pubkey: ` - The public key, as base-58 encoded string, of the account that received the reward - - `lamports: `- number of reward lamports credited or debited by the account, as a i64 - - `postBalance: ` - account balance in lamports after the reward was applied - - `rewardType: ` - type of reward: "fee", "rent", "voting", "staking" - - `commission: ` - vote account commission when the reward was credited, only present for voting and staking rewards - - `blockTime: ` - estimated production time, as Unix timestamp (seconds since the Unix epoch). null if not available - - `blockHeight: ` - the number of blocks beneath this block - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0","id":1, - "method":"getBlock", - "params": [ - 430, - { - "encoding": "json", - "maxSupportedTransactionVersion":0, - "transactionDetails":"full", - "rewards":false - } - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "blockHeight": 428, - "blockTime": null, - "blockhash": "3Eq21vXNB5s86c62bVuUfTeaMif1N2kUqRPBmGRJhyTA", - "parentSlot": 429, - "previousBlockhash": "mfcyqEXB3DnHXki6KjjmZck6YjmZLvpAByy2fj4nh6B", - "transactions": [ - { - "meta": { - "err": null, - "fee": 5000, - "innerInstructions": [], - "logMessages": [], - "postBalances": [499998932500, 26858640, 1, 1, 1], - "postTokenBalances": [], - "preBalances": [499998937500, 26858640, 1, 1, 1], - "preTokenBalances": [], - "rewards": null, - "status": { - "Ok": null - } - }, - "transaction": { - "message": { - "accountKeys": [ - "3UVYmECPPMZSCqWKfENfuoTv51fTDTWicX9xmBD2euKe", - "AjozzgE83A3x1sHNUR64hfH7zaEBWeMaFuAN9kQgujrc", - "SysvarS1otHashes111111111111111111111111111", - "SysvarC1ock11111111111111111111111111111111", - "Vote111111111111111111111111111111111111111" - ], - "header": { - "numReadonlySignedAccounts": 0, - "numReadonlyUnsignedAccounts": 3, - "numRequiredSignatures": 1 - }, - "instructions": [ - { - "accounts": [1, 2, 3, 0], - "data": "37u9WtQpcm6ULa3WRQHmj49EPs4if7o9f1jSRVZpm2dvihR9C8jY4NqEwXUbLwx15HBSNcP1", - "programIdIndex": 4 - } - ], - "recentBlockhash": "mfcyqEXB3DnHXki6KjjmZck6YjmZLvpAByy2fj4nh6B" - }, - "signatures": [ - "2nBhEBYYvfaAe16UMNqRHre4YNSskvuYgx3M6E4JP1oDYvZEJHvoPzyUidNgNX5r9sTyN1J9UxtbCXy2rqYcuyuv" - ] - } - } - ] - }, - "id": 1 -} -``` - - - - ---- - -#### Transaction Structure - -Transactions are quite different from those on other blockchains. Be sure to review [Anatomy of a Transaction](developing/programming-model/transactions.md) to learn about transactions on Solana. - -The JSON structure of a transaction is defined as follows: - -- `signatures: ` - A list of base-58 encoded signatures applied to the transaction. The list is always of length `message.header.numRequiredSignatures` and not empty. The signature at index `i` corresponds to the public key at index `i` in `message.accountKeys`. The first one is used as the [transaction id](../../terminology.md#transaction-id). -- `message: ` - Defines the content of the transaction. - - `accountKeys: ` - List of base-58 encoded public keys used by the transaction, including by the instructions and for signatures. The first `message.header.numRequiredSignatures` public keys must sign the transaction. - - `header: ` - Details the account types and signatures required by the transaction. - - `numRequiredSignatures: ` - The total number of signatures required to make the transaction valid. The signatures must match the first `numRequiredSignatures` of `message.accountKeys`. - - `numReadonlySignedAccounts: ` - The last `numReadonlySignedAccounts` of the signed keys are read-only accounts. Programs may process multiple transactions that load read-only accounts within a single PoH entry, but are not permitted to credit or debit lamports or modify account data. Transactions targeting the same read-write account are evaluated sequentially. - - `numReadonlyUnsignedAccounts: ` - The last `numReadonlyUnsignedAccounts` of the unsigned keys are read-only accounts. - - `recentBlockhash: ` - A base-58 encoded hash of a recent block in the ledger used to prevent transaction duplication and to give transactions lifetimes. - - `instructions: ` - List of program instructions that will be executed in sequence and committed in one atomic transaction if all succeed. - - `programIdIndex: ` - Index into the `message.accountKeys` array indicating the program account that executes this instruction. - - `accounts: ` - List of ordered indices into the `message.accountKeys` array indicating which accounts to pass to the program. - - `data: ` - The program input data encoded in a base-58 string. - - `addressTableLookups: ` - List of address table lookups used by a transaction to dynamically load addresses from on-chain address lookup tables. Undefined if `maxSupportedTransactionVersion` is not set. - - `accountKey: ` - base-58 encoded public key for an address lookup table account. - - `writableIndexes: ` - List of indices used to load addresses of writable accounts from a lookup table. - - `readonlyIndexes: ` - List of indices used to load addresses of readonly accounts from a lookup table. - -#### Inner Instructions Structure - -The Solana runtime records the cross-program instructions that are invoked during transaction processing and makes these available for greater transparency of what was executed on-chain per transaction instruction. Invoked instructions are grouped by the originating transaction instruction and are listed in order of processing. - -The JSON structure of inner instructions is defined as a list of objects in the following structure: - -- `index: number` - Index of the transaction instruction from which the inner instruction(s) originated -- `instructions: ` - Ordered list of inner program instructions that were invoked during a single transaction instruction. - - `programIdIndex: ` - Index into the `message.accountKeys` array indicating the program account that executes this instruction. - - `accounts: ` - List of ordered indices into the `message.accountKeys` array indicating which accounts to pass to the program. - - `data: ` - The program input data encoded in a base-58 string. - -#### Token Balances Structure - -The JSON structure of token balances is defined as a list of objects in the following structure: - -- `accountIndex: ` - Index of the account in which the token balance is provided for. -- `mint: ` - Pubkey of the token's mint. -- `owner: ` - Pubkey of token balance's owner. -- `programId: ` - Pubkey of the Token program that owns the account. -- `uiTokenAmount: ` - - - `amount: ` - Raw amount of tokens as a string, ignoring decimals. - - `decimals: ` - Number of decimals configured for token's mint. - - `uiAmount: ` - Token amount as a float, accounting for decimals. **DEPRECATED** - - `uiAmountString: ` - Token amount as a string, accounting for decimals. - - diff --git a/docs/src/api/methods/_getBlockCommitment.mdx b/docs/src/api/methods/_getBlockCommitment.mdx deleted file mode 100644 index c12fc186cf..0000000000 --- a/docs/src/api/methods/_getBlockCommitment.mdx +++ /dev/null @@ -1,70 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getBlockCommitment - -Returns commitment for particular block - - - - - -### Parameters: - - - block number, identified by Slot - - -### Result: - -The result field will be a JSON object containing: - -- `commitment` - commitment, comprising either: - - `` - Unknown block - - `` - commitment, array of u64 integers logging the amount of cluster stake in lamports that has voted on the block at each depth from 0 to `MAX_LOCKOUT_HISTORY` + 1 -- `totalStake` - total active stake, in lamports, of the current epoch - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", "id": 1, - "method": "getBlockCommitment", - "params":[5] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "commitment": [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 10, 32 - ], - "totalStake": 42 - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getBlockHeight.mdx b/docs/src/api/methods/_getBlockHeight.mdx deleted file mode 100644 index 9b8a07d0fd..0000000000 --- a/docs/src/api/methods/_getBlockHeight.mdx +++ /dev/null @@ -1,73 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getBlockHeight - -Returns the current block height of the node - - - - - -### Parameters: - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - -### Result: - -- `` - Current block height - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc":"2.0","id":1, - "method":"getBlockHeight" - } -' -``` - -Result: - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": 1233, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getBlockProduction.mdx b/docs/src/api/methods/_getBlockProduction.mdx deleted file mode 100644 index eed1b5e6fb..0000000000 --- a/docs/src/api/methods/_getBlockProduction.mdx +++ /dev/null @@ -1,97 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getBlockProduction - -Returns recent block production information from the current or previous epoch. - - - - - -### Parameters: - - - -Configuration object containing the following fields: - - - - - Only return results for this validator identity (base-58 encoded) - - - -Slot range to return block production for. If parameter not provided, defaults to current epoch. - -- `firstSlot: ` - first slot to return block production information for (inclusive) -- (optional) `lastSlot: ` - last slot to return block production information for (inclusive). If parameter not provided, defaults to the highest slot - - - - - -### Result: - -The result will be an RpcResponse JSON object with `value` equal to: - -- `` - - `byIdentity: ` - a dictionary of validator identities, - as base-58 encoded strings. Value is a two element array containing the - number of leader slots and the number of blocks produced. - - `range: ` - Block production slot range - - `firstSlot: ` - first slot of the block production information (inclusive) - - `lastSlot: ` - last slot of block production information (inclusive) - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getBlockProduction"} -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 9887 - }, - "value": { - "byIdentity": { - "85iYT5RuzRTDgjyRa3cP8SYhM2j21fj7NhfJ3peu1DPr": [9888, 9886] - }, - "range": { - "firstSlot": 0, - "lastSlot": 9887 - } - } - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getBlockTime.mdx b/docs/src/api/methods/_getBlockTime.mdx deleted file mode 100644 index 7fc991b5b8..0000000000 --- a/docs/src/api/methods/_getBlockTime.mdx +++ /dev/null @@ -1,81 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getBlockTime - -Returns the estimated production time of a block. - -:::info -Each validator reports their UTC time to the ledger on a regular interval by -intermittently adding a timestamp to a Vote for a particular block. A requested -block's time is calculated from the stake-weighted mean of the Vote timestamps -in a set of recent blocks recorded on the ledger. -::: - - - - - -### Parameters: - - - block number, identified by Slot - - -### Result: - -- `` - estimated production time, as Unix timestamp (seconds since the Unix epoch) - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc":"2.0", "id":1, - "method": "getBlockTime", - "params":[5] - } -' -``` - -### Response: - -When a block time is available: - -```json -{ - "jsonrpc": "2.0", - "result": 1574721591, - "id": 1 -} -``` - -When a block time is not available: - -```json -{ - "jsonrpc": "2.0", - "error": { - "code": -32004, - "message": "Block not available for slot 150" - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getBlocks.mdx b/docs/src/api/methods/_getBlocks.mdx deleted file mode 100644 index d46927939b..0000000000 --- a/docs/src/api/methods/_getBlocks.mdx +++ /dev/null @@ -1,86 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getBlocks - -Returns a list of confirmed blocks between two slots - - - - - -### Parameters: - - - start_slot, as u64 integer - - - - end_slot, as u64 integer (must be no more than 500,000 blocks - higher than the `start_slot`) - - - - -Configuration object containing the following fields: - - - -- "processed" is not supported - - - - - -### Result: - -The result field will be an array of u64 integers listing confirmed blocks -between `start_slot` and either `end_slot` - if provided, or latest confirmed block, -inclusive. Max range allowed is 500,000 slots. - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", "id": 1, - "method": "getBlocks", - "params": [ - 5, 10 - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": [5, 6, 7, 8, 9, 10], - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getBlocksWithLimit.mdx b/docs/src/api/methods/_getBlocksWithLimit.mdx deleted file mode 100644 index 04586dea30..0000000000 --- a/docs/src/api/methods/_getBlocksWithLimit.mdx +++ /dev/null @@ -1,84 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getBlocksWithLimit - -Returns a list of confirmed blocks starting at the given slot - - - - - -### Parameters: - - - start_slot, as u64 integer - - - - limit, as u64 integer (must be no more than 500,000 blocks higher - than the start_slot) - - - - -Configuration object containing the following field: - - - -- "processed" is not supported - - - - - -### Result: - -The result field will be an array of u64 integers listing confirmed blocks -starting at `start_slot` for up to `limit` blocks, inclusive. - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id":1, - "method":"getBlocksWithLimit", - "params":[5, 3] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": [5, 6, 7], - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getClusterNodes.mdx b/docs/src/api/methods/_getClusterNodes.mdx deleted file mode 100644 index 735e3aff27..0000000000 --- a/docs/src/api/methods/_getClusterNodes.mdx +++ /dev/null @@ -1,71 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getClusterNodes - -Returns information about all the nodes participating in the cluster - - - - -### Parameters: - -**None** - -### Result: - -The result field will be an array of JSON objects, each with the following sub fields: - -- `pubkey: ` - Node public key, as base-58 encoded string -- `gossip: ` - Gossip network address for the node -- `tpu: ` - TPU network address for the node -- `rpc: ` - JSON RPC network address for the node, or `null` if the JSON RPC service is not enabled -- `version: ` - The software version of the node, or `null` if the version information is not available -- `featureSet: ` - The unique identifier of the node's feature set -- `shredVersion: ` - The shred version the node has been configured to use - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", "id": 1, - "method": "getClusterNodes" - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": [ - { - "gossip": "10.239.6.48:8001", - "pubkey": "9QzsJf7LPLj8GkXbYT3LFDKqsj2hHG7TA3xinJHu8epQ", - "rpc": "10.239.6.48:8899", - "tpu": "10.239.6.48:8856", - "version": "1.0.0 c375ce1f" - } - ], - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getEpochInfo.mdx b/docs/src/api/methods/_getEpochInfo.mdx deleted file mode 100644 index 4b8cb1c23b..0000000000 --- a/docs/src/api/methods/_getEpochInfo.mdx +++ /dev/null @@ -1,81 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getEpochInfo - -Returns information about the current epoch - - - - - -### Parameters: - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - -### Result: - -The result field will be an object with the following fields: - -- `absoluteSlot: ` - the current slot -- `blockHeight: ` - the current block height -- `epoch: ` - the current epoch -- `slotIndex: ` - the current slot relative to the start of the current epoch -- `slotsInEpoch: ` - the number of slots in this epoch -- `transactionCount: ` - total number of transactions processed without error since genesis - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getEpochInfo"} -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "absoluteSlot": 166598, - "blockHeight": 166500, - "epoch": 27, - "slotIndex": 2790, - "slotsInEpoch": 8192, - "transactionCount": 22661093 - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getEpochSchedule.mdx b/docs/src/api/methods/_getEpochSchedule.mdx deleted file mode 100644 index 2e11e8a4be..0000000000 --- a/docs/src/api/methods/_getEpochSchedule.mdx +++ /dev/null @@ -1,67 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getEpochSchedule - -Returns the epoch schedule information from this cluster's genesis config - - - - -### Parameters: - -**None** - -### Result: - -The result field will be an object with the following fields: - -- `slotsPerEpoch: ` - the maximum number of slots in each epoch -- `leaderScheduleSlotOffset: ` - the number of slots before beginning of an epoch to calculate a leader schedule for that epoch -- `warmup: ` - whether epochs start short and grow -- `firstNormalEpoch: ` - first normal-length epoch, log2(slotsPerEpoch) - log2(MINIMUM_SLOTS_PER_EPOCH) -- `firstNormalSlot: ` - MINIMUM_SLOTS_PER_EPOCH \* (2.pow(firstNormalEpoch) - 1) - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc":"2.0","id":1, - "method":"getEpochSchedule" - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "firstNormalEpoch": 8, - "firstNormalSlot": 8160, - "leaderScheduleSlotOffset": 8192, - "slotsPerEpoch": 8192, - "warmup": true - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getFeeForMessage.mdx b/docs/src/api/methods/_getFeeForMessage.mdx deleted file mode 100644 index 85a81f589b..0000000000 --- a/docs/src/api/methods/_getFeeForMessage.mdx +++ /dev/null @@ -1,86 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getFeeForMessage - -Get the fee the network will charge for a particular Message - -:::caution -**NEW: This method is only available in solana-core v1.9 or newer. Please use -[getFees](#getFees) for solana-core v1.8** -::: - - - - -### Parameters: - - - Base-64 encoded Message - - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - -### Result: - -- `` - Fee corresponding to the message at the specified blockhash - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' -{ - "id":1, - "jsonrpc":"2.0", - "method":"getFeeForMessage", - "params":[ - "AQABAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAA", - { - "commitment":"processed" - } - ] -} -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { "context": { "slot": 5068 }, "value": 5000 }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getFirstAvailableBlock.mdx b/docs/src/api/methods/_getFirstAvailableBlock.mdx deleted file mode 100644 index 97139e17b5..0000000000 --- a/docs/src/api/methods/_getFirstAvailableBlock.mdx +++ /dev/null @@ -1,50 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getFirstAvailableBlock - -Returns the slot of the lowest confirmed block that has not been purged from the ledger - - - - -### Parameters: - -**None** - -### Result: - -- `` - Slot - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc":"2.0","id":1, - "method":"getFirstAvailableBlock" - } -' -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 250000, "id": 1 } -``` - - - - diff --git a/docs/src/api/methods/_getGenesisHash.mdx b/docs/src/api/methods/_getGenesisHash.mdx deleted file mode 100644 index 4a7802d8b1..0000000000 --- a/docs/src/api/methods/_getGenesisHash.mdx +++ /dev/null @@ -1,51 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getGenesisHash - -Returns the genesis hash - - - - -### Parameters: - -**None** - -### Result: - -- `` - a Hash as base-58 encoded string - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getGenesisHash"} -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": "GH7ome3EiwEr7tu9JuTh2dpYWBJK3z69Xm1ZE3MEE6JC", - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getHealth.mdx b/docs/src/api/methods/_getHealth.mdx deleted file mode 100644 index ceb30cc40f..0000000000 --- a/docs/src/api/methods/_getHealth.mdx +++ /dev/null @@ -1,83 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getHealth - -Returns the current health of the node. A healthy node is one that is within -`HEALTH_CHECK_SLOT_DISTANCE` slots of the latest cluster confirmed slot. - - - - -### Parameters: - -**None** - -### Result: - -If the node is healthy: "ok" - -If the node is unhealthy, a JSON RPC error response is returned. The specifics of the error response are **UNSTABLE** and may change in the future - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getHealth"} -' -``` - -### Response: - -Healthy Result: - -```json -{ "jsonrpc": "2.0", "result": "ok", "id": 1 } -``` - -Unhealthy Result (generic): - -```json -{ - "jsonrpc": "2.0", - "error": { - "code": -32005, - "message": "Node is unhealthy", - "data": {} - }, - "id": 1 -} -``` - -Unhealthy Result (if additional information is available) - -```json -{ - "jsonrpc": "2.0", - "error": { - "code": -32005, - "message": "Node is behind by 42 slots", - "data": { - "numSlotsBehind": 42 - } - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getHighestSnapshotSlot.mdx b/docs/src/api/methods/_getHighestSnapshotSlot.mdx deleted file mode 100644 index 73e0603bae..0000000000 --- a/docs/src/api/methods/_getHighestSnapshotSlot.mdx +++ /dev/null @@ -1,78 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getHighestSnapshotSlot - -Returns the highest slot information that the node has snapshots for. - -This will find the highest full snapshot slot, and the highest incremental -snapshot slot _based on_ the full snapshot slot, if there is one. - -:::caution -NEW: This method is only available in solana-core v1.9 or newer. Please use -[getSnapshotSlot](/api/http#getsnapshotslot) for solana-core v1.8 -::: - - - - -### Parameters: - -**None** - -### Result: - -When the node has a snapshot, this returns a JSON object with the following fields: - -- `full: ` - Highest full snapshot slot -- `incremental: ` - Highest incremental snapshot slot _based on_ `full` - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1,"method":"getHighestSnapshotSlot"} -' -``` - -### Response: - -Result when the node has a snapshot: - -```json -{ - "jsonrpc": "2.0", - "result": { - "full": 100, - "incremental": 110 - }, - "id": 1 -} -``` - -Result when the node has no snapshot: - -```json -{ - "jsonrpc": "2.0", - "error": { "code": -32008, "message": "No snapshot" }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getIdentity.mdx b/docs/src/api/methods/_getIdentity.mdx deleted file mode 100644 index 263ebb28d7..0000000000 --- a/docs/src/api/methods/_getIdentity.mdx +++ /dev/null @@ -1,55 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getIdentity - -Returns the identity pubkey for the current node - - - - -### Parameters: - -**None** - -### Result: - -The result field will be a JSON object with the following fields: - -- `identity` - the identity pubkey of the current node \(as a base-58 encoded string\) - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getIdentity"} -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "identity": "2r1F4iWqVcb8M1DbAjQuFpebkQHY9hcVU4WuW2DJBppN" - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getInflationGovernor.mdx b/docs/src/api/methods/_getInflationGovernor.mdx deleted file mode 100644 index 206fa9a60c..0000000000 --- a/docs/src/api/methods/_getInflationGovernor.mdx +++ /dev/null @@ -1,75 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getInflationGovernor - -Returns the current inflation governor - - - - -### Parameters: - - - -Configuration object containing the following fields: - - - - - -### Result: - -The result field will be a JSON object with the following fields: - -- `initial: ` - the initial inflation percentage from time 0 -- `terminal: ` - terminal inflation percentage -- `taper: ` - rate per year at which inflation is lowered. (Rate reduction is derived using the target slot time in genesis config) -- `foundation: ` - percentage of total inflation allocated to the foundation -- `foundationTerm: ` - duration of foundation pool inflation in years - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getInflationGovernor"} -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "foundation": 0.05, - "foundationTerm": 7, - "initial": 0.15, - "taper": 0.15, - "terminal": 0.015 - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getInflationRate.mdx b/docs/src/api/methods/_getInflationRate.mdx deleted file mode 100644 index 1cc987aab1..0000000000 --- a/docs/src/api/methods/_getInflationRate.mdx +++ /dev/null @@ -1,62 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getInflationRate - -Returns the specific inflation values for the current epoch - - - - -### Parameters: - -**None** - -### Result: - -The result field will be a JSON object with the following fields: - -- `total: ` - total inflation -- `validator: ` -inflation allocated to validators -- `foundation: ` - inflation allocated to the foundation -- `epoch: ` - epoch for which these values are valid - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getInflationRate"} -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "epoch": 100, - "foundation": 0.001, - "total": 0.149, - "validator": 0.148 - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getInflationReward.mdx b/docs/src/api/methods/_getInflationReward.mdx deleted file mode 100644 index 840a6f520f..0000000000 --- a/docs/src/api/methods/_getInflationReward.mdx +++ /dev/null @@ -1,101 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getInflationReward - -Returns the inflation / staking reward for a list of addresses for an epoch - - - - -### Parameters: - - - An array of addresses to query, as base-58 encoded strings - - - - -Configuration object containing the following fields: - - - - - An epoch for which the reward occurs. If omitted, the previous epoch will be - used - - - - The minimum slot that the request can be evaluated at - - - - -### Result: - -The result field will be a JSON array with the following fields: - -- `epoch: ` - epoch for which reward occured -- `effectiveSlot: ` - the slot in which the rewards are effective -- `amount: ` - reward amount in lamports -- `postBalance: ` - post balance of the account in lamports -- `commission: ` - vote account commission when the reward was credited - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getInflationReward", - "params": [ - [ - "6dmNQ5jwLeLk5REvio1JcMshcbvkYMwy26sJ8pbkvStu", - "BGsqMegLpV6n6Ve146sSX2dTjUMj3M92HnU8BbNRMhF2" - ], - {"epoch": 2} - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": [ - { - "amount": 2500, - "effectiveSlot": 224, - "epoch": 2, - "postBalance": 499999442500 - }, - null - ], - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getLargestAccounts.mdx b/docs/src/api/methods/_getLargestAccounts.mdx deleted file mode 100644 index aef3e9f820..0000000000 --- a/docs/src/api/methods/_getLargestAccounts.mdx +++ /dev/null @@ -1,150 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getLargestAccounts - -Returns the 20 largest accounts, by lamport balance (results may be cached up to two hours) - - - - -### Parameters: - - - -Configuration object containing the following fields: - - - - - filter results by account type - - - - - - -### Result: - -The result will be an RpcResponse JSON object with `value` equal to an array of `` containing: - -- `address: ` - base-58 encoded address of the account -- `lamports: ` - number of lamports in the account, as a u64 - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getLargestAccounts"} -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 54 - }, - "value": [ - { - "lamports": 999974, - "address": "99P8ZgtJYe1buSK8JXkvpLh8xPsCFuLYhz9hQFNw93WJ" - }, - { - "lamports": 42, - "address": "uPwWLo16MVehpyWqsLkK3Ka8nLowWvAHbBChqv2FZeL" - }, - { - "lamports": 42, - "address": "aYJCgU7REfu3XF8b3QhkqgqQvLizx8zxuLBHA25PzDS" - }, - { - "lamports": 42, - "address": "CTvHVtQ4gd4gUcw3bdVgZJJqApXE9nCbbbP4VTS5wE1D" - }, - { - "lamports": 20, - "address": "4fq3xJ6kfrh9RkJQsmVd5gNMvJbuSHfErywvEjNQDPxu" - }, - { - "lamports": 4, - "address": "AXJADheGVp9cruP8WYu46oNkRbeASngN5fPCMVGQqNHa" - }, - { - "lamports": 2, - "address": "8NT8yS6LiwNprgW4yM1jPPow7CwRUotddBVkrkWgYp24" - }, - { - "lamports": 1, - "address": "SysvarEpochSchedu1e111111111111111111111111" - }, - { - "lamports": 1, - "address": "11111111111111111111111111111111" - }, - { - "lamports": 1, - "address": "Stake11111111111111111111111111111111111111" - }, - { - "lamports": 1, - "address": "SysvarC1ock11111111111111111111111111111111" - }, - { - "lamports": 1, - "address": "StakeConfig11111111111111111111111111111111" - }, - { - "lamports": 1, - "address": "SysvarRent111111111111111111111111111111111" - }, - { - "lamports": 1, - "address": "Config1111111111111111111111111111111111111" - }, - { - "lamports": 1, - "address": "SysvarStakeHistory1111111111111111111111111" - }, - { - "lamports": 1, - "address": "SysvarRecentB1ockHashes11111111111111111111" - }, - { - "lamports": 1, - "address": "SysvarFees111111111111111111111111111111111" - }, - { - "lamports": 1, - "address": "Vote111111111111111111111111111111111111111" - } - ] - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getLatestBlockhash.mdx b/docs/src/api/methods/_getLatestBlockhash.mdx deleted file mode 100644 index 85724a785c..0000000000 --- a/docs/src/api/methods/_getLatestBlockhash.mdx +++ /dev/null @@ -1,92 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getLatestBlockhash - -Returns the latest blockhash - -:::caution -NEW: This method is only available in solana-core v1.9 or newer. Please use -[getRecentBlockhash](#getrecentblockhash) for solana-core v1.8 -::: - - - - -### Parameters: - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - -### Result: - -`RpcResponse` - RpcResponse JSON object with `value` field set to a JSON object including: - -- `blockhash: ` - a Hash as base-58 encoded string -- `lastValidBlockHeight: ` - last [block height](../../terminology.md#block-height) at which the blockhash will be valid - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "id":1, - "jsonrpc":"2.0", - "method":"getLatestBlockhash", - "params":[ - { - "commitment":"processed" - } - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 2792 - }, - "value": { - "blockhash": "EkSnNWid2cvwEVnVx9aBqawnmiCNiDgp3gUdkDPTKN1N", - "lastValidBlockHeight": 3090 - } - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getLeaderSchedule.mdx b/docs/src/api/methods/_getLeaderSchedule.mdx deleted file mode 100644 index ee6803cb0e..0000000000 --- a/docs/src/api/methods/_getLeaderSchedule.mdx +++ /dev/null @@ -1,96 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getLeaderSchedule - -Returns the leader schedule for an epoch - - - - -### Parameters: - - -Fetch the leader schedule for the epoch that corresponds to the provided slot. - -
  • If unspecified, the leader schedule for the current epoch is fetched
  • - -
    - - - -Configuration object containing the following fields: - - - - - Only return results for this validator identity (base-58 encoded) - - - - -### Result: - -Returns a result with one of the two following values: - -- `` - if requested epoch is not found, or -- `` - the result field will be a dictionary of validator identities, - as base-58 encoded strings, and their corresponding leader slot indices as values - (indices are relative to the first slot in the requested epoch) - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getLeaderSchedule", - "params": [ - null, - { - "identity": "4Qkev8aNZcqFNSRhQzwyLMFSsi94jHqE8WNVTJzTP99F" - } - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "4Qkev8aNZcqFNSRhQzwyLMFSsi94jHqE8WNVTJzTP99F": [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63 - ] - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getMaxRetransmitSlot.mdx b/docs/src/api/methods/_getMaxRetransmitSlot.mdx deleted file mode 100644 index 17a104750e..0000000000 --- a/docs/src/api/methods/_getMaxRetransmitSlot.mdx +++ /dev/null @@ -1,48 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getMaxRetransmitSlot - -Get the max slot seen from retransmit stage. - - - - -### Parameters: - -**None** - -### Result: - -`` - Slot number - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getMaxRetransmitSlot"} -' -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 1234, "id": 1 } -``` - - - - diff --git a/docs/src/api/methods/_getMaxShredInsertSlot.mdx b/docs/src/api/methods/_getMaxShredInsertSlot.mdx deleted file mode 100644 index d776870ed9..0000000000 --- a/docs/src/api/methods/_getMaxShredInsertSlot.mdx +++ /dev/null @@ -1,48 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getMaxShredInsertSlot - -Get the max slot seen from after shred insert. - - - - -### Parameters: - -**None** - -### Result: - -`` - Slot number - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getMaxShredInsertSlot"} -' -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 1234, "id": 1 } -``` - - - - diff --git a/docs/src/api/methods/_getMinimumBalanceForRentExemption.mdx b/docs/src/api/methods/_getMinimumBalanceForRentExemption.mdx deleted file mode 100644 index 3f52828441..0000000000 --- a/docs/src/api/methods/_getMinimumBalanceForRentExemption.mdx +++ /dev/null @@ -1,67 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getMinimumBalanceForRentExemption - -Returns minimum balance required to make account rent exempt. - - - - -### Parameters: - - - the Account's data length - - - - -Configuration object containing the following fields: - - - - - -### Result: - -`` - minimum lamports required in the Account to remain rent free - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", "id": 1, - "method": "getMinimumBalanceForRentExemption", - "params": [50] - } -' -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 500, "id": 1 } -``` - - - - diff --git a/docs/src/api/methods/_getMultipleAccounts.mdx b/docs/src/api/methods/_getMultipleAccounts.mdx deleted file mode 100644 index b9c73a2a4d..0000000000 --- a/docs/src/api/methods/_getMultipleAccounts.mdx +++ /dev/null @@ -1,148 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getMultipleAccounts - -Returns the account information for a list of Pubkeys. - - - - -### Parameters: - - - An array of Pubkeys to query, as base-58 encoded strings (up to a maximum of - 100) - - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - Request a slice of the account's data. - - - `length: ` - number of bytes to return - - `offset: ` - byte offset from which to start reading - -:::info -Data slicing is only available for base58, base64, or base64+zstd encodings. -::: - - - - -encoding format for the returned Account data - - - -
    - -- `base58` is slow and limited to less than 129 bytes of Account data. -- `base64` will return base64 encoded data for Account data of any size. -- `base64+zstd` compresses the Account data using [Zstandard](https://facebook.github.io/zstd/) - and base64-encodes the result. -- [`jsonParsed` encoding](/api/http#parsed-responses) attempts to use program-specific state parsers to - return more human-readable and explicit account state data. -- If `jsonParsed` is requested but a parser cannot be found, the field falls back to `base64` - encoding, detectable when the `data` field is type ``. - -
    - -
    - -
    - -### Result: - -The result will be a JSON object with `value` equal to an array of: - -- `` - if the account at that Pubkey doesn't exist, or -- `` - a JSON object containing: - - `lamports: ` - number of lamports assigned to this account, as a u64 - - `owner: ` - base-58 encoded Pubkey of the program this account has been assigned to - - `data: <[string, encoding]|object>` - data associated with the account, either as encoded binary data or JSON format `{: }` - depending on encoding parameter - - `executable: ` - boolean indicating if the account contains a program \(and is strictly read-only\) - - `rentEpoch: ` - the epoch at which this account will next owe rent, as u64 - - `size: ` - the data size of the account - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getMultipleAccounts", - "params": [ - [ - "vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg", - "4fYNw3dojWmQ4dXtSGE9epjRGy9pFSx62YypT7avPYvA" - ], - { - "encoding": "base58" - } - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 1 - }, - "value": [ - { - "data": ["", "base64"], - "executable": false, - "lamports": 1000000000, - "owner": "11111111111111111111111111111111", - "rentEpoch": 2, - "space": 16 - }, - { - "data": ["", "base64"], - "executable": false, - "lamports": 5000000000, - "owner": "11111111111111111111111111111111", - "rentEpoch": 2, - "space": 0 - } - ] - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getProgramAccounts.mdx b/docs/src/api/methods/_getProgramAccounts.mdx deleted file mode 100644 index 0104a0cfd8..0000000000 --- a/docs/src/api/methods/_getProgramAccounts.mdx +++ /dev/null @@ -1,164 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getProgramAccounts - -Returns all accounts owned by the provided program Pubkey - - - - -### Parameters: - - - Pubkey of program, as base-58 encoded string - - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - wrap the result in an RpcResponse JSON object - - - - -encoding format for the returned Account data - - - -
    - -- `base58` is slow and limited to less than 129 bytes of Account data. -- `base64` will return base64 encoded data for Account data of any size. -- `base64+zstd` compresses the Account data using [Zstandard](https://facebook.github.io/zstd/) and - base64-encodes the result. -- [`jsonParsed` encoding](/api/http#parsed-responses) attempts to use program-specific state - parsers to return more human-readable and explicit account state data. -- If `jsonParsed` is requested but a parser cannot be found, the field falls back - to `base64` encoding, detectable when the `data` field is type ``. - -
    - -
    - - - Request a slice of the account's data. - - - `length: ` - number of bytes to return - - `offset: ` - byte offset from which to start reading - -:::info -Data slicing is only available for base58, base64, or base64+zstd encodings. -::: - - - - -filter results using up to 4 filter objects - -:::info -The resultant account(s) must meet **ALL** filter criteria to be included in the returned results -::: - - - -
    - -### Result: - -By default, the result field will be an array of JSON objects. - -:::info -If `withContext` flag is set the array will be wrapped in an RpcResponse JSON object. -::: - -The resultant response array will contain: - -- `pubkey: ` - the account Pubkey as base-58 encoded string -- `account: ` - a JSON object, with the following sub fields: - - `lamports: ` - number of lamports assigned to this account, as a u64 - - `owner: ` - base-58 encoded Pubkey of the program this account has been assigned to - - `data: <[string,encoding]|object>` - data associated with the account, either as encoded binary data or JSON format `{: }` - depending on encoding parameter - - `executable: ` - boolean indicating if the account contains a program \(and is strictly read-only\) - - `rentEpoch: ` - the epoch at which this account will next owe rent, as u64 - - `size: ` - the data size of the account - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getProgramAccounts", - "params": [ - "4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T", - { - "filters": [ - { - "dataSize": 17 - }, - { - "memcmp": { - "offset": 4, - "bytes": "3Mc6vR" - } - } - ] - } - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": [ - { - "account": { - "data": "2R9jLfiAQ9bgdcw6h8s44439", - "executable": false, - "lamports": 15298080, - "owner": "4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T", - "rentEpoch": 28, - "space": 42 - }, - "pubkey": "CxELquR1gPP8wHe33gZ4QxqGB3sZ9RSwsJ2KshVewkFY" - } - ], - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getRecentPerformanceSamples.mdx b/docs/src/api/methods/_getRecentPerformanceSamples.mdx deleted file mode 100644 index 9b07a1322e..0000000000 --- a/docs/src/api/methods/_getRecentPerformanceSamples.mdx +++ /dev/null @@ -1,103 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getRecentPerformanceSamples - -Returns a list of recent performance samples, in reverse slot order. Performance samples are taken every 60 seconds and -include the number of transactions and slots that occur in a given time window. - - - - -### Parameters: - - - -number of samples to return (maximum 720) - - - -### Result: - -An array of `RpcPerfSample` with the following fields: - -- `slot: ` - Slot in which sample was taken at -- `numTransactions: ` - Number of transactions processed during the sample period -- `numSlots: ` - Number of slots completed during the sample period -- `samplePeriodSecs: ` - Number of seconds in a sample window -- `numNonVoteTransaction: ` - Number of non-vote transactions processed during the - sample period. - -:::info -`numNonVoteTransaction` is present starting with v1.15. - -To get a number of voting transactions compute:
    -`numTransactions - numNonVoteTransaction` -::: - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc":"2.0", "id":1, - "method": "getRecentPerformanceSamples", - "params": [4]} -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": [ - { - "numSlots": 126, - "numTransactions": 126, - "numNonVoteTransaction": 1, - "samplePeriodSecs": 60, - "slot": 348125 - }, - { - "numSlots": 126, - "numTransactions": 126, - "numNonVoteTransaction": 1, - "samplePeriodSecs": 60, - "slot": 347999 - }, - { - "numSlots": 125, - "numTransactions": 125, - "numNonVoteTransaction": 0, - "samplePeriodSecs": 60, - "slot": 347873 - }, - { - "numSlots": 125, - "numTransactions": 125, - "numNonVoteTransaction": 0, - "samplePeriodSecs": 60, - "slot": 347748 - } - ], - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getRecentPrioritizationFees.mdx b/docs/src/api/methods/_getRecentPrioritizationFees.mdx deleted file mode 100644 index 2c88d51260..0000000000 --- a/docs/src/api/methods/_getRecentPrioritizationFees.mdx +++ /dev/null @@ -1,95 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getRecentPrioritizationFees - -Returns a list of prioritization fees from recent blocks. - -:::info -Currently, a node's prioritization-fee cache stores data from up to 150 blocks. -::: - - - - -### Parameters: - - - -An array of Account addresses (up to a maximum of 128 addresses), as base-58 encoded strings - -:::note -If this parameter is provided, the response will reflect a fee to land a transaction locking all of the provided accounts as writable. -::: - - - -### Result: - -An array of `RpcPrioritizationFee` with the following fields: - -- `slot: ` - slot in which the fee was observed -- `prioritizationFee: ` - the per-compute-unit fee paid by at least - one successfully landed transaction, specified in increments of micro-lamports (0.000001 lamports) - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc":"2.0", "id":1, - "method": "getRecentPrioritizationFees", - "params": [ - ["CxELquR1gPP8wHe33gZ4QxqGB3sZ9RSwsJ2KshVewkFY"] - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": [ - { - "slot": 348125, - "prioritizationFee": 0 - }, - { - "slot": 348126, - "prioritizationFee": 1000 - }, - { - "slot": 348127, - "prioritizationFee": 500 - }, - { - "slot": 348128, - "prioritizationFee": 0 - }, - { - "slot": 348129, - "prioritizationFee": 1234 - } - ], - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getSignatureStatuses.mdx b/docs/src/api/methods/_getSignatureStatuses.mdx deleted file mode 100644 index 9617d7d228..0000000000 --- a/docs/src/api/methods/_getSignatureStatuses.mdx +++ /dev/null @@ -1,114 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getSignatureStatuses - -Returns the statuses of a list of signatures. Each signature must be a [txid](/terminology#transaction-id), the first signature of a transaction. - -:::info -Unless the `searchTransactionHistory` configuration parameter is included, -this method only searches the recent status cache of signatures, which -retains statuses for all active slots plus `MAX_RECENT_BLOCKHASHES` rooted slots. -::: - - - - -### Parameters: - - - An array of transaction signatures to confirm, as base-58 encoded strings (up - to a maximum of 256) - - - - -Configuration object containing the following fields: - - - -if `true` - a Solana node will search its ledger cache for any signatures not -found in the recent status cache - - - - - -### Result: - -An array of `RpcResponse` consisting of either: - -- `` - Unknown transaction, or -- `` - - `slot: ` - The slot the transaction was processed - - `confirmations: ` - Number of blocks since signature confirmation, null if rooted, as well as finalized by a supermajority of the cluster - - `err: ` - Error if transaction failed, null if transaction succeeded. - See [TransactionError definitions](https://github.com/solana-labs/solana/blob/c0c60386544ec9a9ec7119229f37386d9f070523/sdk/src/transaction/error.rs#L13) - - `confirmationStatus: ` - The transaction's cluster confirmation status; - Either `processed`, `confirmed`, or `finalized`. See [Commitment](/api/http#configuring-state-commitment) for more on optimistic confirmation. - - DEPRECATED: `status: ` - Transaction status - - `"Ok": ` - Transaction was successful - - `"Err": ` - Transaction failed with TransactionError - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getSignatureStatuses", - "params": [ - [ - "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW" - ], - { - "searchTransactionHistory": true - } - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 82 - }, - "value": [ - { - "slot": 48, - "confirmations": null, - "err": null, - "status": { - "Ok": null - }, - "confirmationStatus": "finalized" - }, - null - ] - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getSignaturesForAddress.mdx b/docs/src/api/methods/_getSignaturesForAddress.mdx deleted file mode 100644 index dc0517058d..0000000000 --- a/docs/src/api/methods/_getSignaturesForAddress.mdx +++ /dev/null @@ -1,117 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getSignaturesForAddress - -Returns signatures for confirmed transactions that include the given address in -their `accountKeys` list. Returns signatures backwards in time from the -provided signature or most recent confirmed block - - - - -### Parameters: - - - Account address as base-58 encoded string - - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - maximum transaction signatures to return (between 1 and 1,000). - - - - start searching backwards from this transaction signature. If not provided the - search starts from the top of the highest max confirmed block. - - - - search until this transaction signature, if found before limit reached - - - - -### Result: - -An array of ``, ordered from **newest** to **oldest** transaction, containing transaction -signature information with the following fields: - -- `signature: ` - transaction signature as base-58 encoded string -- `slot: ` - The slot that contains the block with the transaction -- `err: ` - Error if transaction failed, null if transaction succeeded. - See [TransactionError definitions](https://github.com/solana-labs/solana/blob/c0c60386544ec9a9ec7119229f37386d9f070523/sdk/src/transaction/error.rs#L13) - for more info. -- `memo: ` - Memo associated with the transaction, null if no memo is present -- `blockTime: ` - estimated production time, as Unix timestamp (seconds since the Unix epoch) - of when transaction was processed. null if not available. -- `confirmationStatus: ` - The transaction's cluster confirmation status; - Either `processed`, `confirmed`, or `finalized`. See [Commitment](/api/http#configuring-state-commitment) - for more on optimistic confirmation. - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getSignaturesForAddress", - "params": [ - "Vote111111111111111111111111111111111111111", - { - "limit": 1 - } - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": [ - { - "err": null, - "memo": null, - "signature": "5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv", - "slot": 114, - "blockTime": null - } - ], - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getSlot.mdx b/docs/src/api/methods/_getSlot.mdx deleted file mode 100644 index 8693f8f3bb..0000000000 --- a/docs/src/api/methods/_getSlot.mdx +++ /dev/null @@ -1,63 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getSlot - -Returns the slot that has reached the [given or default commitment level](/api/http#configuring-state-commitment) - - - - -### Parameters: - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - -### Result: - -`` - Current slot - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getSlot"} -' -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 1234, "id": 1 } -``` - - - - diff --git a/docs/src/api/methods/_getSlotLeader.mdx b/docs/src/api/methods/_getSlotLeader.mdx deleted file mode 100644 index 7f8550ee1b..0000000000 --- a/docs/src/api/methods/_getSlotLeader.mdx +++ /dev/null @@ -1,67 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getSlotLeader - -Returns the current slot leader - - - - -### Parameters: - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - -### Result: - -`` - Node identity Pubkey as base-58 encoded string - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getSlotLeader"} -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": "ENvAW7JScgYq6o4zKZwewtkzzJgDzuJAFxYasvmEQdpS", - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getSlotLeaders.mdx b/docs/src/api/methods/_getSlotLeaders.mdx deleted file mode 100644 index 386a74fb44..0000000000 --- a/docs/src/api/methods/_getSlotLeaders.mdx +++ /dev/null @@ -1,77 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getSlotLeaders - -Returns the slot leaders for a given slot range - - - - -### Parameters: - - - Start slot, as u64 integer - - - - Limit, as u64 integer (between 1 and 5,000) - - -### Result: - -`` - array of Node identity public keys as base-58 encoded strings - - - - - -### Code sample: - -If the current slot is `#99` - query the next `10` leaders with the following request: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc":"2.0", "id": 1, - "method": "getSlotLeaders", - "params": [100, 10] - } -' -``` - -### Response: - -The first leader returned is the leader for slot `#100`: - -```json -{ - "jsonrpc": "2.0", - "result": [ - "ChorusmmK7i1AxXeiTtQgQZhQNiXYU84ULeaYF1EH15n", - "ChorusmmK7i1AxXeiTtQgQZhQNiXYU84ULeaYF1EH15n", - "ChorusmmK7i1AxXeiTtQgQZhQNiXYU84ULeaYF1EH15n", - "ChorusmmK7i1AxXeiTtQgQZhQNiXYU84ULeaYF1EH15n", - "Awes4Tr6TX8JDzEhCZY2QVNimT6iD1zWHzf1vNyGvpLM", - "Awes4Tr6TX8JDzEhCZY2QVNimT6iD1zWHzf1vNyGvpLM", - "Awes4Tr6TX8JDzEhCZY2QVNimT6iD1zWHzf1vNyGvpLM", - "Awes4Tr6TX8JDzEhCZY2QVNimT6iD1zWHzf1vNyGvpLM", - "DWvDTSh3qfn88UoQTEKRV2JnLt5jtJAVoiCo3ivtMwXP", - "DWvDTSh3qfn88UoQTEKRV2JnLt5jtJAVoiCo3ivtMwXP" - ], - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getStakeActivation.mdx b/docs/src/api/methods/_getStakeActivation.mdx deleted file mode 100644 index 28b2d8a814..0000000000 --- a/docs/src/api/methods/_getStakeActivation.mdx +++ /dev/null @@ -1,96 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getStakeActivation - -Returns epoch activation information for a stake account - - - - -### Parameters: - - - Pubkey of stake Account to query, as base-58 encoded string - - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - epoch for which to calculate activation details. If parameter not provided, - defaults to current epoch. - **DEPRECATED**, inputs other than the current epoch return an error. - - - - -### Result: - -The result will be a JSON object with the following fields: - -- `state: ` - the stake account's activation state, - either: `active`, `inactive`, `activating`, or `deactivating` -- `active: ` - stake active during the epoch -- `inactive: ` - stake inactive during the epoch - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getStakeActivation", - "params": [ - "CYRJWqiSjLitBAcRxPvWpgX3s5TvmN2SuRY3eEYypFvT", - { - "epoch": 4 - } - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "active": 124429280, - "inactive": 73287840, - "state": "activating" - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getStakeMinimumDelegation.mdx b/docs/src/api/methods/_getStakeMinimumDelegation.mdx deleted file mode 100644 index 94e01ac870..0000000000 --- a/docs/src/api/methods/_getStakeMinimumDelegation.mdx +++ /dev/null @@ -1,73 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getStakeMinimumDelegation - -Returns the stake minimum delegation, in lamports. - - - - -### Parameters: - - - -Configuration object containing the following fields: - - - - - -### Result: - -The result will be an RpcResponse JSON object with `value` equal to: - -- `` - The stake minimum delegation, in lamports - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc":"2.0", "id":1, - "method": "getStakeMinimumDelegation" - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 501 - }, - "value": 1000000000 - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getSupply.mdx b/docs/src/api/methods/_getSupply.mdx deleted file mode 100644 index a1d8915a1b..0000000000 --- a/docs/src/api/methods/_getSupply.mdx +++ /dev/null @@ -1,87 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getSupply - -Returns information about the current supply. - - - - -### Parameters: - - - -Configuration object containing the following fields: - - - - - exclude non circulating accounts list from response - - - - -### Result: - -The result will be an RpcResponse JSON object with `value` equal to a JSON object containing: - -- `total: ` - Total supply in lamports -- `circulating: ` - Circulating supply in lamports -- `nonCirculating: ` - Non-circulating supply in lamports -- `nonCirculatingAccounts: ` - an array of account addresses of non-circulating accounts, as strings. If `excludeNonCirculatingAccountsList` is enabled, the returned array will be empty. - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0", "id":1, "method":"getSupply"} -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 1114 - }, - "value": { - "circulating": 16000, - "nonCirculating": 1000000, - "nonCirculatingAccounts": [ - "FEy8pTbP5fEoqMV1GdTz83byuA8EKByqYat1PKDgVAq5", - "9huDUZfxoJ7wGMTffUE7vh1xePqef7gyrLJu9NApncqA", - "3mi1GmwEE3zo2jmfDuzvjSX9ovRXsDUKHvsntpkhuLJ9", - "BYxEJTDerkaRWBem3XgnVcdhppktBXa2HbkHPKj2Ui4Z" - ], - "total": 1016000 - } - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getTokenAccountBalance.mdx b/docs/src/api/methods/_getTokenAccountBalance.mdx deleted file mode 100644 index e0cb785f7d..0000000000 --- a/docs/src/api/methods/_getTokenAccountBalance.mdx +++ /dev/null @@ -1,91 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getTokenAccountBalance - -Returns the token balance of an SPL Token account. - - - - -### Parameters: - - - Pubkey of Token account to query, as base-58 encoded string - - - - -Configuration object containing the following fields: - - - - - -### Result: - -The result will be an RpcResponse JSON object with `value` equal to a JSON object containing: - -- `amount: ` - the raw balance without decimals, a string representation of u64 -- `decimals: ` - number of base 10 digits to the right of the decimal place -- `uiAmount: ` - the balance, using mint-prescribed decimals **DEPRECATED** -- `uiAmountString: ` - the balance as a string, using mint-prescribed decimals - -For more details on returned data, the [Token Balances Structure](#token-balances-structure) -response from [getBlock](#getblock) follows a similar structure. - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", "id": 1, - "method": "getTokenAccountBalance", - "params": [ - "7fUAJdStEuGbc3sM84cKRL6yYaaSstyLSU4ve5oovLS7" - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 1114 - }, - "value": { - "amount": "9864", - "decimals": 2, - "uiAmount": 98.64, - "uiAmountString": "98.64" - }, - "id": 1 - } -} -``` - - - - diff --git a/docs/src/api/methods/_getTokenAccountsByDelegate.mdx b/docs/src/api/methods/_getTokenAccountsByDelegate.mdx deleted file mode 100644 index 7125724573..0000000000 --- a/docs/src/api/methods/_getTokenAccountsByDelegate.mdx +++ /dev/null @@ -1,180 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getTokenAccountsByDelegate - -Returns all SPL Token accounts by approved Delegate. - - - - -### Parameters: - - - Pubkey of account delegate to query, as base-58 encoded string - - - - -A JSON object with one of the following fields: - -- `mint: ` - Pubkey of the specific token Mint to limit accounts to, as base-58 encoded string; or -- `programId: ` - Pubkey of the Token program that owns the accounts, as base-58 encoded string - - - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - Request a slice of the account's data. - - - `length: ` - number of bytes to return - - `offset: ` - byte offset from which to start reading - -:::info -Data slicing is only available for base58, base64, or base64+zstd encodings. -::: - - - - -Encoding format for Account data - - - -
    - -- `base58` is slow and limited to less than 129 bytes of Account data. -- `base64` will return base64 encoded data for Account data of any size. -- `base64+zstd` compresses the Account data using [Zstandard](https://facebook.github.io/zstd/) - and base64-encodes the result. -- `jsonParsed` encoding attempts to use program-specific state parsers to return - more human-readable and explicit account state data. -- If `jsonParsed` is requested but a parser cannot be found, the field falls - back to `base64` encoding, detectable when the `data` field is type `string`. - -
    - -
    - -
    - -### Result: - -The result will be an RpcResponse JSON object with `value` equal to an array of JSON objects, which will contain: - -- `pubkey: ` - the account Pubkey as base-58 encoded string -- `account: ` - a JSON object, with the following sub fields: - - `lamports: ` - number of lamports assigned to this account, as a u64 - - `owner: ` - base-58 encoded Pubkey of the program this account has been assigned to - - `data: ` - Token state data associated with the account, either as encoded binary data or in JSON format `{: }` - - `executable: ` - boolean indicating if the account contains a program (and is strictly read-only\) - - `rentEpoch: ` - the epoch at which this account will next owe rent, as u64 - - `size: ` - the data size of the account - -When the data is requested with the `jsonParsed` encoding a format similar to that of the -[Token Balances Structure](#token-balances-structure) can be expected inside the structure, -both for the `tokenAmount` and the `delegatedAmount` - with the latter being an optional object. - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getTokenAccountsByDelegate", - "params": [ - "4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T", - { - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" - }, - { - "encoding": "jsonParsed" - } - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 1114 - }, - "value": [ - { - "account": { - "data": { - "program": "spl-token", - "parsed": { - "info": { - "tokenAmount": { - "amount": "1", - "decimals": 1, - "uiAmount": 0.1, - "uiAmountString": "0.1" - }, - "delegate": "4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T", - "delegatedAmount": { - "amount": "1", - "decimals": 1, - "uiAmount": 0.1, - "uiAmountString": "0.1" - }, - "state": "initialized", - "isNative": false, - "mint": "3wyAj7Rt1TWVPZVteFJPLa26JmLvdb1CAKEFZm3NY75E", - "owner": "CnPoSPKXu7wJqxe59Fs72tkBeALovhsCxYeFwPCQH9TD" - }, - "type": "account" - }, - "space": 165 - }, - "executable": false, - "lamports": 1726080, - "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "rentEpoch": 4, - "space": 165 - }, - "pubkey": "28YTZEwqtMHWrhWcvv34se7pjS7wctgqzCPB3gReCFKp" - } - ] - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getTokenAccountsByOwner.mdx b/docs/src/api/methods/_getTokenAccountsByOwner.mdx deleted file mode 100644 index 27aa971189..0000000000 --- a/docs/src/api/methods/_getTokenAccountsByOwner.mdx +++ /dev/null @@ -1,179 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getTokenAccountsByOwner - -Returns all SPL Token accounts by token owner. - - - - -### Parameters: - - - Pubkey of account delegate to query, as base-58 encoded string - - - - -A JSON object with one of the following fields: - -- `mint: ` - Pubkey of the specific token Mint to limit accounts to, as base-58 encoded string; or -- `programId: ` - Pubkey of the Token program that owns the accounts, as base-58 encoded string - - - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - Request a slice of the account's data. - - - `length: ` - number of bytes to return - - `offset: ` - byte offset from which to start reading - -:::info -Data slicing is only available for base58, base64, or base64+zstd encodings. -::: - - - - -Encoding format for Account data - - - -
    - -- `base58` is slow and limited to less than 129 bytes of Account data. -- `base64` will return base64 encoded data for Account data of any size. -- `base64+zstd` compresses the Account data using [Zstandard](https://facebook.github.io/zstd/) - and base64-encodes the result. -- `jsonParsed` encoding attempts to use program-specific state parsers to return - more human-readable and explicit account state data. -- If `jsonParsed` is requested but a parser cannot be found, the field falls - back to `base64` encoding, detectable when the `data` field is type `string`. - -
    - -
    - -
    - -### Result: - -The result will be an RpcResponse JSON object with `value` equal to an array of JSON objects, which will contain: - -- `pubkey: ` - the account Pubkey as base-58 encoded string -- `account: ` - a JSON object, with the following sub fields: - - `lamports: ` - number of lamports assigned to this account, as a u64 - - `owner: ` - base-58 encoded Pubkey of the program this account has been assigned to - - `data: ` - Token state data associated with the account, either as encoded binary data or in JSON format `{: }` - - `executable: ` - boolean indicating if the account contains a program \(and is strictly read-only\) - - `rentEpoch: ` - the epoch at which this account will next owe rent, as u64 - - `size: ` - the data size of the account - -When the data is requested with the `jsonParsed` encoding a format similar to that of the [Token Balances Structure](/api/http#token-balances-structure) can be expected inside the structure, both for the `tokenAmount` and the `delegatedAmount` - with the latter being an optional object. - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getTokenAccountsByOwner", - "params": [ - "4Qkev8aNZcqFNSRhQzwyLMFSsi94jHqE8WNVTJzTP99F", - { - "mint": "3wyAj7Rt1TWVPZVteFJPLa26JmLvdb1CAKEFZm3NY75E" - }, - { - "encoding": "jsonParsed" - } - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 1114 - }, - "value": [ - { - "account": { - "data": { - "program": "spl-token", - "parsed": { - "accountType": "account", - "info": { - "tokenAmount": { - "amount": "1", - "decimals": 1, - "uiAmount": 0.1, - "uiAmountString": "0.1" - }, - "delegate": "4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T", - "delegatedAmount": { - "amount": "1", - "decimals": 1, - "uiAmount": 0.1, - "uiAmountString": "0.1" - }, - "state": "initialized", - "isNative": false, - "mint": "3wyAj7Rt1TWVPZVteFJPLa26JmLvdb1CAKEFZm3NY75E", - "owner": "4Qkev8aNZcqFNSRhQzwyLMFSsi94jHqE8WNVTJzTP99F" - }, - "type": "account" - }, - "space": 165 - }, - "executable": false, - "lamports": 1726080, - "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "rentEpoch": 4, - "space": 165 - }, - "pubkey": "C2gJg6tKpQs41PRS1nC8aw3ZKNZK3HQQZGVrDFDup5nx" - } - ] - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getTokenLargestAccounts.mdx b/docs/src/api/methods/_getTokenLargestAccounts.mdx deleted file mode 100644 index 387f00ad2e..0000000000 --- a/docs/src/api/methods/_getTokenLargestAccounts.mdx +++ /dev/null @@ -1,99 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getTokenLargestAccounts - -Returns the 20 largest accounts of a particular SPL Token type. - - - - -### Parameters: - - - Pubkey of the token Mint to query, as base-58 encoded string - - - - -Configuration object containing the following fields: - - - - - -### Result: - -The result will be an RpcResponse JSON object with `value` equal to an array of JSON objects containing: - -- `address: ` - the address of the token account -- `amount: ` - the raw token account balance without decimals, a string representation of u64 -- `decimals: ` - number of base 10 digits to the right of the decimal place -- `uiAmount: ` - the token account balance, using mint-prescribed decimals **DEPRECATED** -- `uiAmountString: ` - the token account balance as a string, using mint-prescribed decimals - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", "id": 1, - "method": "getTokenLargestAccounts", - "params": [ - "3wyAj7Rt1TWVPZVteFJPLa26JmLvdb1CAKEFZm3NY75E" - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 1114 - }, - "value": [ - { - "address": "FYjHNoFtSQ5uijKrZFyYAxvEr87hsKXkXcxkcmkBAf4r", - "amount": "771", - "decimals": 2, - "uiAmount": 7.71, - "uiAmountString": "7.71" - }, - { - "address": "BnsywxTcaYeNUtzrPxQUvzAWxfzZe3ZLUJ4wMMuLESnu", - "amount": "229", - "decimals": 2, - "uiAmount": 2.29, - "uiAmountString": "2.29" - } - ] - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getTokenSupply.mdx b/docs/src/api/methods/_getTokenSupply.mdx deleted file mode 100644 index af42feee06..0000000000 --- a/docs/src/api/methods/_getTokenSupply.mdx +++ /dev/null @@ -1,88 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getTokenSupply - -Returns the total supply of an SPL Token type. - - - - -### Parameters: - - - Pubkey of the token Mint to query, as base-58 encoded string - - - - -Configuration object containing the following fields: - - - - - -### Result: - -The result will be an RpcResponse JSON object with `value` equal to a JSON object containing: - -- `amount: ` - the raw total token supply without decimals, a string representation of u64 -- `decimals: ` - number of base 10 digits to the right of the decimal place -- `uiAmount: ` - the total token supply, using mint-prescribed decimals **DEPRECATED** -- `uiAmountString: ` - the total token supply as a string, using mint-prescribed decimals - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", "id": 1, - "method": "getTokenSupply", - "params": [ - "3wyAj7Rt1TWVPZVteFJPLa26JmLvdb1CAKEFZm3NY75E" - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 1114 - }, - "value": { - "amount": "100000", - "decimals": 2, - "uiAmount": 1000, - "uiAmountString": "1000" - } - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getTransaction.mdx b/docs/src/api/methods/_getTransaction.mdx deleted file mode 100644 index 8a70a3219b..0000000000 --- a/docs/src/api/methods/_getTransaction.mdx +++ /dev/null @@ -1,172 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getTransaction - -Returns transaction details for a confirmed transaction - - - - -### Parameters: - - - Transaction signature, as base-58 encoded string - - - - -Configuration object containing the following fields: - - - - - Set the max transaction version to return in responses. If the requested - transaction is a higher version, an error will be returned. If this parameter - is omitted, only legacy transactions will be returned, and any versioned - transaction will prompt the error. - - - - -Encoding for the returned Transaction - - - -
    - -- `jsonParsed` encoding attempts to use program-specific state parsers to return - more human-readable and explicit data in the `transaction.message.instructions` list. -- If `jsonParsed` is requested but a parser cannot be found, the instruction - falls back to regular JSON encoding (`accounts`, `data`, and `programIdIndex` fields). - -
    - -
    - -
    - -### Result: - -- `` - if transaction is not found or not confirmed -- `` - if transaction is confirmed, an object with the following fields: - - `slot: ` - the slot this transaction was processed in - - `transaction: ` - [Transaction](#transaction-structure) object, either in JSON format or encoded binary data, depending on encoding parameter - - `blockTime: ` - estimated production time, as Unix timestamp (seconds since the Unix epoch) of when the transaction was processed. null if not available - - `meta: ` - transaction status metadata object: - - `err: ` - Error if transaction failed, null if transaction succeeded. [TransactionError definitions](https://docs.rs/solana-sdk/VERSION_FOR_DOCS_RS/solana_sdk/transaction/enum.TransactionError.html) - - `fee: ` - fee this transaction was charged, as u64 integer - - `preBalances: ` - array of u64 account balances from before the transaction was processed - - `postBalances: ` - array of u64 account balances after the transaction was processed - - `innerInstructions: ` - List of [inner instructions](#inner-instructions-structure) or `null` if inner instruction recording was not enabled during this transaction - - `preTokenBalances: ` - List of [token balances](#token-balances-structure) from before the transaction was processed or omitted if token balance recording was not yet enabled during this transaction - - `postTokenBalances: ` - List of [token balances](#token-balances-structure) from after the transaction was processed or omitted if token balance recording was not yet enabled during this transaction - - `logMessages: ` - array of string log messages or `null` if log message recording was not enabled during this transaction - - DEPRECATED: `status: ` - Transaction status - - `"Ok": ` - Transaction was successful - - `"Err": ` - Transaction failed with TransactionError - - `rewards: ` - transaction-level rewards, populated if rewards are requested; an array of JSON objects containing: - - `pubkey: ` - The public key, as base-58 encoded string, of the account that received the reward - - `lamports: `- number of reward lamports credited or debited by the account, as a i64 - - `postBalance: ` - account balance in lamports after the reward was applied - - `rewardType: ` - type of reward: currently only "rent", other types may be added in the future - - `commission: ` - vote account commission when the reward was credited, only present for voting and staking rewards - - `loadedAddresses: ` - Transaction addresses loaded from address lookup tables. Undefined if `maxSupportedTransactionVersion` is not set in request params, or if `jsonParsed` encoding is set in request params. - - `writable: ` - Ordered list of base-58 encoded addresses for writable loaded accounts - - `readonly: ` - Ordered list of base-58 encoded addresses for readonly loaded accounts - - `returnData: ` - the most-recent return data generated by an instruction in the transaction, with the following fields: - - `programId: ` - the program that generated the return data, as base-58 encoded Pubkey - - `data: <[string, encoding]>` - the return data itself, as base-64 encoded binary data - - `computeUnitsConsumed: ` - number of [compute units](developing/programming-model/runtime.md#compute-budget) consumed by the transaction - - `version: <"legacy"|number|undefined>` - Transaction version. Undefined if `maxSupportedTransactionVersion` is not set in request params. - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getTransaction", - "params": [ - "2nBhEBYYvfaAe16UMNqRHre4YNSskvuYgx3M6E4JP1oDYvZEJHvoPzyUidNgNX5r9sTyN1J9UxtbCXy2rqYcuyuv", - "json" - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "meta": { - "err": null, - "fee": 5000, - "innerInstructions": [], - "postBalances": [499998932500, 26858640, 1, 1, 1], - "postTokenBalances": [], - "preBalances": [499998937500, 26858640, 1, 1, 1], - "preTokenBalances": [], - "rewards": [], - "status": { - "Ok": null - } - }, - "slot": 430, - "transaction": { - "message": { - "accountKeys": [ - "3UVYmECPPMZSCqWKfENfuoTv51fTDTWicX9xmBD2euKe", - "AjozzgE83A3x1sHNUR64hfH7zaEBWeMaFuAN9kQgujrc", - "SysvarS1otHashes111111111111111111111111111", - "SysvarC1ock11111111111111111111111111111111", - "Vote111111111111111111111111111111111111111" - ], - "header": { - "numReadonlySignedAccounts": 0, - "numReadonlyUnsignedAccounts": 3, - "numRequiredSignatures": 1 - }, - "instructions": [ - { - "accounts": [1, 2, 3, 0], - "data": "37u9WtQpcm6ULa3WRQHmj49EPs4if7o9f1jSRVZpm2dvihR9C8jY4NqEwXUbLwx15HBSNcP1", - "programIdIndex": 4 - } - ], - "recentBlockhash": "mfcyqEXB3DnHXki6KjjmZck6YjmZLvpAByy2fj4nh6B" - }, - "signatures": [ - "2nBhEBYYvfaAe16UMNqRHre4YNSskvuYgx3M6E4JP1oDYvZEJHvoPzyUidNgNX5r9sTyN1J9UxtbCXy2rqYcuyuv" - ] - } - }, - "blockTime": null, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_getTransactionCount.mdx b/docs/src/api/methods/_getTransactionCount.mdx deleted file mode 100644 index 3a966a1f66..0000000000 --- a/docs/src/api/methods/_getTransactionCount.mdx +++ /dev/null @@ -1,63 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getTransactionCount - -Returns the current Transaction count from the ledger - - - - -### Parameters: - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - -### Result: - -`` - the current Transaction count from the ledger - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getTransactionCount"} -' -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 268, "id": 1 } -``` - - - - diff --git a/docs/src/api/methods/_getVersion.mdx b/docs/src/api/methods/_getVersion.mdx deleted file mode 100644 index a5e9bc2f0e..0000000000 --- a/docs/src/api/methods/_getVersion.mdx +++ /dev/null @@ -1,51 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getVersion - -Returns the current Solana version running on the node - - - - -### Parameters: - -**None** - -### Result: - -The result field will be a JSON object with the following fields: - -- `solana-core` - software version of solana-core as a `string` -- `feature-set` - unique identifier of the current software's feature set as a `u32` - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getVersion"} -' -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": { "feature-set": 2891131721, "solana-core": "1.16.7" }, "id": 1 } -``` - - - - diff --git a/docs/src/api/methods/_getVoteAccounts.mdx b/docs/src/api/methods/_getVoteAccounts.mdx deleted file mode 100644 index 04a57a3aa4..0000000000 --- a/docs/src/api/methods/_getVoteAccounts.mdx +++ /dev/null @@ -1,114 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## getVoteAccounts - -Returns the account info and associated stake for all the voting accounts in the current bank. - - - - -### Parameters: - - - -Configuration object containing the following fields: - - - - - Only return results for this validator vote address (base-58 encoded) - - - - Do not filter out delinquent validators with no stake - - - - Specify the number of slots behind the tip that a validator must fall to be - considered delinquent. **NOTE:** For the sake of consistency between ecosystem - products, _it is **not** recommended that this argument be specified._ - - - - -### Result: - -The result field will be a JSON object of `current` and `delinquent` accounts, -each containing an array of JSON objects with the following sub fields: - -- `votePubkey: ` - Vote account address, as base-58 encoded string -- `nodePubkey: ` - Validator identity, as base-58 encoded string -- `activatedStake: ` - the stake, in lamports, delegated to this vote account and active in this epoch -- `epochVoteAccount: ` - bool, whether the vote account is staked for this epoch -- `commission: ` - percentage (0-100) of rewards payout owed to the vote account -- `lastVote: ` - Most recent slot voted on by this vote account -- `epochCredits: ` - Latest history of earned credits for up to five epochs, as an array of arrays containing: `[epoch, credits, previousCredits]`. -- `rootSlot: ` - Current root slot for this vote account - - - - - -### Code sample: - -Restrict results to a single validator vote account: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "getVoteAccounts", - "params": [ - { - "votePubkey": "3ZT31jkAGhUaw8jsy4bTknwBMP8i4Eueh52By4zXcsVw" - } - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "current": [ - { - "commission": 0, - "epochVoteAccount": true, - "epochCredits": [ - [1, 64, 0], - [2, 192, 64] - ], - "nodePubkey": "B97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD", - "lastVote": 147, - "activatedStake": 42, - "votePubkey": "3ZT31jkAGhUaw8jsy4bTknwBMP8i4Eueh52By4zXcsVw" - } - ], - "delinquent": [] - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_isBlockhashValid.mdx b/docs/src/api/methods/_isBlockhashValid.mdx deleted file mode 100644 index d8903dc0ee..0000000000 --- a/docs/src/api/methods/_isBlockhashValid.mdx +++ /dev/null @@ -1,89 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## isBlockhashValid - -Returns whether a blockhash is still valid or not - -:::caution -NEW: This method is only available in solana-core v1.9 or newer. Please use -[getFeeCalculatorForBlockhash](#getfeecalculatorforblockhash) for solana-core v1.8 -::: - - - - -### Parameters: - - - the blockhash of the block to evauluate, as base-58 encoded string - - - - -Configuration object containing the following fields: - - - - - The minimum slot that the request can be evaluated at - - - - -### Result: - -`` - `true` if the blockhash is still valid - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "id":45, - "jsonrpc":"2.0", - "method":"isBlockhashValid", - "params":[ - "J7rBdM6AecPDEZp8aPq5iPSNKVkU5Q76F3oAV4eW5wsW", - {"commitment":"processed"} - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 2483 - }, - "value": false - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_minimumLedgerSlot.mdx b/docs/src/api/methods/_minimumLedgerSlot.mdx deleted file mode 100644 index 1ac63315d9..0000000000 --- a/docs/src/api/methods/_minimumLedgerSlot.mdx +++ /dev/null @@ -1,52 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## minimumLedgerSlot - -Returns the lowest slot that the node has information about in its ledger. - -:::info -This value may increase over time if the node is configured to purge older ledger data -::: - - - - -### Parameters: - -**None** - -### Result: - -`u64` - Minimum ledger slot number - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"minimumLedgerSlot"} -' -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 1234, "id": 1 } -``` - - - - diff --git a/docs/src/api/methods/_requestAirdrop.mdx b/docs/src/api/methods/_requestAirdrop.mdx deleted file mode 100644 index 7a9cf3527f..0000000000 --- a/docs/src/api/methods/_requestAirdrop.mdx +++ /dev/null @@ -1,78 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## requestAirdrop - -Requests an airdrop of lamports to a Pubkey - - - - -### Parameters: - - - Pubkey of account to receive lamports, as a base-58 encoded string - - - - lamports to airdrop, as a "u64" - - - - -Configuration object containing the following fields: - - - - - -### Result: - -`` - Transaction Signature of the airdrop, as a base-58 encoded string - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", "id": 1, - "method": "requestAirdrop", - "params": [ - "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri", - 1000000000 - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW", - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_sendTransaction.mdx b/docs/src/api/methods/_sendTransaction.mdx deleted file mode 100644 index fc9978aaee..0000000000 --- a/docs/src/api/methods/_sendTransaction.mdx +++ /dev/null @@ -1,124 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## sendTransaction - -Submits a signed transaction to the cluster for processing. - -This method does not alter the transaction in any way; it relays the -transaction created by clients to the node as-is. - -If the node's rpc service receives the transaction, this method immediately -succeeds, without waiting for any confirmations. A successful response from -this method does not guarantee the transaction is processed or confirmed by the -cluster. - -While the rpc service will reasonably retry to submit it, the transaction -could be rejected if transaction's `recent_blockhash` expires before it lands. - -Use [`getSignatureStatuses`](#getsignaturestatuses) to ensure a transaction is processed and confirmed. - -Before submitting, the following preflight checks are performed: - -1. The transaction signatures are verified -2. The transaction is simulated against the bank slot specified by the preflight - commitment. On failure an error will be returned. Preflight checks may be - disabled if desired. It is recommended to specify the same commitment and - preflight commitment to avoid confusing behavior. - -The returned signature is the first signature in the transaction, which -is used to identify the transaction ([transaction id](../../terminology.md#transaction-id)). -This identifier can be easily extracted from the transaction data before -submission. - - - - -### Parameters: - - - Fully-signed Transaction, as encoded string. - - - - -Configuration object containing the following optional fields: - - - -Encoding used for the transaction data. - -Values: `base58` (_slow_, **DEPRECATED**), or `base64`. - - - - - if "true", skip the preflight transaction checks - - - - Commitment level to use for preflight. - - - - Maximum number of times for the RPC node to retry sending the transaction to - the leader. If this parameter not provided, the RPC node will retry the - transaction until it is finalized or until the blockhash expires. - - - - set the minimum slot at which to perform preflight transaction checks - - - - -### Result: - -`` - First Transaction Signature embedded in the transaction, as base-58 encoded string ([transaction id](../../terminology.md#transaction-id)) - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "sendTransaction", - "params": [ - "4hXTCkRzt9WyecNzV1XPgCDfGAZzQKNxLXgynz5QDuWWPSAZBZSHptvWRL3BjCvzUXRdKvHL2b7yGrRQcWyaqsaBCncVG7BFggS8w9snUts67BSh3EqKpXLUm5UMHfD7ZBe9GhARjbNQMLJ1QD3Spr6oMTBU6EhdB4RD8CP2xUxr2u3d6fos36PD98XS6oX8TQjLpsMwncs5DAMiD4nNnR8NBfyghGCWvCVifVwvA8B8TJxE1aiyiv2L429BCWfyzAme5sZW8rDb14NeCQHhZbtNqfXhcp2tAnaAT" - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": "2id3YC2jK9G5Wo2phDx4gJVAew8DcY5NAojnVuao8rkxwPYPe8cSwE5GzhEgJA2y8fVjDEo6iR6ykBvDxrTQrtpb", - "id": 1 -} -``` - - - - diff --git a/docs/src/api/methods/_simulateTransaction.mdx b/docs/src/api/methods/_simulateTransaction.mdx deleted file mode 100644 index 9a245846d1..0000000000 --- a/docs/src/api/methods/_simulateTransaction.mdx +++ /dev/null @@ -1,174 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## simulateTransaction - -Simulate sending a transaction - - - - -### Parameters: - - - -Transaction, as an encoded string. - -:::note -The transaction must have a valid blockhash, but is not required to be signed. -::: - - - - - -Configuration object containing the following fields: - - - Commitment level to simulate the transaction at - - - - if `true` the transaction signatures will be verified (conflicts with - `replaceRecentBlockhash`) - - - - if `true` the transaction recent blockhash will be replaced with the most - recent blockhash. (conflicts with `sigVerify`) - - - - the minimum slot that the request can be evaluated at - - - - -Encoding used for the transaction data. - -Values: `base58` (_slow_, **DEPRECATED**), or `base64`. - - - - - -Accounts configuration object containing the following fields: - - - An `array` of accounts to return, as base-58 encoded strings - - - - -encoding for returned Account data - - - -
    - -- `jsonParsed` encoding attempts to use program-specific state - parsers to return more human-readable and explicit account state data. -- If `jsonParsed` is requested but a [parser cannot be found](https://github.com/solana-labs/solana/blob/cfd0a00ae2ba85a6d76757df8b4fa38ed242d185/account-decoder/src/parse_account_data.rs#L98-L100), the field falls - back to `base64` encoding, detectable when the returned `accounts.data` field is type `string`. - -
    - -
    - -
    - -
    - -### Result: - -The result will be an RpcResponse JSON object with `value` set to a JSON object with the following fields: - -- `err: ` - Error if transaction failed, null if transaction succeeded. [TransactionError definitions](https://github.com/solana-labs/solana/blob/c0c60386544ec9a9ec7119229f37386d9f070523/sdk/src/transaction/error.rs#L13) -- `logs: ` - Array of log messages the transaction instructions output during execution, null if simulation failed before the transaction was able to execute (for example due to an invalid blockhash or signature verification failure) -- `accounts: ` - array of accounts with the same length as the `accounts.addresses` array in the request - - `` - if the account doesn't exist or if `err` is not null - - `` - otherwise, a JSON object containing: - - `lamports: ` - number of lamports assigned to this account, as a u64 - - `owner: ` - base-58 encoded Pubkey of the program this account has been assigned to - - `data: <[string, encoding]|object>` - data associated with the account, either as encoded binary data or JSON format `{: }` - depending on encoding parameter - - `executable: ` - boolean indicating if the account contains a program \(and is strictly read-only\) - - `rentEpoch: ` - the epoch at which this account will next owe rent, as u64 -- `unitsConsumed: ` - The number of compute budget units consumed during the processing of this transaction -- `returnData: ` - the most-recent return data generated by an instruction in the transaction, with the following fields: - - `programId: ` - the program that generated the return data, as base-58 encoded Pubkey - - `data: <[string, encoding]>` - the return data itself, as base-64 encoded binary data - - - - - -### Code sample: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d ' - { - "jsonrpc": "2.0", - "id": 1, - "method": "simulateTransaction", - "params": [ - "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEDArczbMia1tLmq7zz4DinMNN0pJ1JtLdqIJPUw3YrGCzYAMHBsgN27lcgB6H2WQvFgyZuJYHa46puOQo9yQ8CVQbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV+/wCp20C7Wj2aiuk5TReAXo+VTVg8QTHjs0UjNMMKCvpzZ+ABAgEBARU=", - { - "encoding":"base64", - } - ] - } -' -``` - -### Response: - -```json -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 218 - }, - "value": { - "err": null, - "accounts": null, - "logs": [ - "Program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri invoke [1]", - "Program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri consumed 2366 of 1400000 compute units", - "Program return: 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri KgAAAAAAAAA=", - "Program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri success" - ], - "returnData": { - "data": ["Kg==", "base64"], - "programId": "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri" - }, - "unitsConsumed": 2366 - } - }, - "id": 1 -} -``` - - - - diff --git a/docs/src/api/websocket.md b/docs/src/api/websocket.md deleted file mode 100644 index d409072f46..0000000000 --- a/docs/src/api/websocket.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: RPC Websocket API -displayed_sidebar: apiWebsocketMethodsSidebar -hide_table_of_contents: true ---- - -After connecting to the RPC PubSub websocket at `ws://
    /`: - -- Submit subscription requests to the websocket using the methods below -- Multiple subscriptions may be active at once -- Many subscriptions take the optional [`commitment` parameter](/api/http#configuring-state-commitment), defining how finalized a change should be to trigger a notification. For subscriptions, if commitment is unspecified, the default value is `finalized`. - -## RPC PubSub WebSocket Endpoint - -**Default port:** 8900 e.g. ws://localhost:8900, [http://192.168.1.88:8900](http://192.168.1.88:8900) - -## Methods - -The following methods are supported in the RPC Websocket API: - -import AccountSubscribe from "./websocket/\_accountSubscribe.mdx" - - - -import AccountUnsubscribe from "./websocket/\_accountUnsubscribe.mdx" - - - -import BlockSubscribe from "./websocket/\_blockSubscribe.mdx" - - - -import BlockUnsubscribe from "./websocket/\_blockUnsubscribe.mdx" - - - -import LogsSubscribe from "./websocket/\_logsSubscribe.mdx" - - - -import LogsUnsubscribe from "./websocket/\_logsUnsubscribe.mdx" - - - -import ProgramSubscribe from "./websocket/\_programSubscribe.mdx" - - - -import ProgramUnsubscribe from "./websocket/\_programUnsubscribe.mdx" - - - -import SignatureSubscribe from "./websocket/\_signatureSubscribe.mdx" - - - -import SignatureUnsubscribe from "./websocket/\_signatureUnsubscribe.mdx" - - - -import SlotSubscribe from "./websocket/\_slotSubscribe.mdx" - - - -import SlotUnsubscribe from "./websocket/\_slotUnsubscribe.mdx" - - - -import SlotsUpdatesSubscribe from "./websocket/\_slotsUpdatesSubscribe.mdx" - - - -import SlotsUpdatesUnsubscribe from "./websocket/\_slotsUpdatesUnsubscribe.mdx" - - - -import RootSubscribe from "./websocket/\_rootSubscribe.mdx" - - - -import RootUnsubscribe from "./websocket/\_rootUnsubscribe.mdx" - - - -import VoteSubscribe from "./websocket/\_voteSubscribe.mdx" - - - -import VoteUnsubscribe from "./websocket/\_voteUnsubscribe.mdx" - - diff --git a/docs/src/api/websocket/_accountSubscribe.mdx b/docs/src/api/websocket/_accountSubscribe.mdx deleted file mode 100644 index f86e214a64..0000000000 --- a/docs/src/api/websocket/_accountSubscribe.mdx +++ /dev/null @@ -1,160 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## accountSubscribe - -Subscribe to an account to receive notifications when the lamports or data for a given account public key changes - - - - -### Parameters: - - - Account Pubkey, as base-58 encoded string - - - - -Configuration object containing the following fields: - - - - - -Encoding format for Account data - - - -
    - -- `base58` is slow. -- `jsonParsed` encoding attempts to use program-specific state parsers to return more - human-readable and explicit account state data -- If `jsonParsed` is requested but a parser cannot be found, the field falls back to - binary encoding, detectable when the `data`field is type`string`. - -
    - -
    - -
    - -### Result: - -`` - Subscription id \(needed to unsubscribe\) - -
    - - - -### Code sample: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "method": "accountSubscribe", - "params": [ - "CM78CPUeXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNH12", - { - "encoding": "jsonParsed", - "commitment": "finalized" - } - ] -} -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 23784, "id": 1 } -``` - - -
    - -#### Notification Format: - -The notification format is the same as seen in the [getAccountInfo](#getAccountInfo) RPC HTTP method. - -Base58 encoding: - -```json -{ - "jsonrpc": "2.0", - "method": "accountNotification", - "params": { - "result": { - "context": { - "slot": 5199307 - }, - "value": { - "data": [ - "11116bv5nS2h3y12kD1yUKeMZvGcKLSjQgX6BeV7u1FrjeJcKfsHPXHRDEHrBesJhZyqnnq9qJeUuF7WHxiuLuL5twc38w2TXNLxnDbjmuR", - "base58" - ], - "executable": false, - "lamports": 33594, - "owner": "11111111111111111111111111111111", - "rentEpoch": 635, - "space": 80 - } - }, - "subscription": 23784 - } -} -``` - -Parsed-JSON encoding: - -```json -{ - "jsonrpc": "2.0", - "method": "accountNotification", - "params": { - "result": { - "context": { - "slot": 5199307 - }, - "value": { - "data": { - "program": "nonce", - "parsed": { - "type": "initialized", - "info": { - "authority": "Bbqg1M4YVVfbhEzwA9SpC9FhsaG83YMTYoR4a8oTDLX", - "blockhash": "LUaQTmM7WbMRiATdMMHaRGakPtCkc2GHtH57STKXs6k", - "feeCalculator": { - "lamportsPerSignature": 5000 - } - } - } - }, - "executable": false, - "lamports": 33594, - "owner": "11111111111111111111111111111111", - "rentEpoch": 635, - "space": 80 - } - }, - "subscription": 23784 - } -} -``` - -
    diff --git a/docs/src/api/websocket/_accountUnsubscribe.mdx b/docs/src/api/websocket/_accountUnsubscribe.mdx deleted file mode 100644 index d3a90de9ab..0000000000 --- a/docs/src/api/websocket/_accountUnsubscribe.mdx +++ /dev/null @@ -1,53 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## accountUnsubscribe - -Unsubscribe from account change notifications - - - - -### Parameters: - - - id of the account Subscription to cancel - - -### Result: - -`` - unsubscribe success message - - - - - -### Code sample: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "method": "accountUnsubscribe", - "params": [0] -} -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": true, "id": 1 } -``` - - - - diff --git a/docs/src/api/websocket/_blockSubscribe.mdx b/docs/src/api/websocket/_blockSubscribe.mdx deleted file mode 100644 index b86543798e..0000000000 --- a/docs/src/api/websocket/_blockSubscribe.mdx +++ /dev/null @@ -1,378 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## blockSubscribe - -Subscribe to receive notification anytime a new block is Confirmed or Finalized. - -:::caution -This subscription is **unstable** and only available if the validator was started -with the `--rpc-pubsub-enable-block-subscription` flag. - -**NOTE: The format of this subscription may change in the future** -::: - - - - -### Parameters: - - - -filter criteria for the logs to receive results by account type; currently supported: - - - all - include all transactions in block - - - - -A JSON object with the following field: - -- `mentionsAccountOrProgram: ` - return only transactions that mention the provided public key (as base-58 encoded string). If no mentions in a given block, then no notification will be sent. - - - - - - - -Configuration object containing the following fields: - - -
  • - the default is finalized -
  • -
  • - processed is not supported. -
  • -
    - - - -encoding format for each returned Transaction - - - -
    - -- `jsonParsed` attempts to use program-specific instruction parsers to return - more human-readable and explicit data in the `transaction.message.instructions` list. -- If `jsonParsed` is requested but a parser cannot be found, the instruction - falls back to regular JSON encoding (`accounts`, `data`, and `programIdIndex` fields). - -
    - -
    - - - -level of transaction detail to return - - - -
    - -- If `accounts` are requested, transaction details only include signatures and - an annotated list of accounts in each transaction. -- Transaction metadata is limited to only: fee, err, pre_balances, - post_balances, pre_token_balances, and post_token_balances. - -
    - -
    - - - -the max transaction version to return in responses. - -
    - -- If the requested block contains a transaction with a higher version, an - error will be returned. -- If this parameter is omitted, only legacy transactions will be returned, and - a block containing any versioned transaction will prompt the error. - -
    - -
    - - - whether to populate the `rewards` array. If parameter not provided, the - default includes rewards. - - -
    - -### Result: - -`integer` - subscription id \(needed to unsubscribe\) - -
    - - - -### Code sample: - -```json -{ - "jsonrpc": "2.0", - "id": "1", - "method": "blockSubscribe", - "params": ["all"] -} -``` - -```json -{ - "jsonrpc": "2.0", - "id": "1", - "method": "blockSubscribe", - "params": [ - { - "mentionsAccountOrProgram": "LieKvPRE8XeX3Y2xVNHjKlpAScD12lYySBVQ4HqoJ5op" - }, - { - "commitment": "confirmed", - "encoding": "base64", - "showRewards": true, - "transactionDetails": "full" - } - ] -} -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 0, "id": 1 } -``` - - -
    - -#### Notification Format: - -The notification will be an object with the following fields: - -- `slot: ` - The corresponding slot. -- `err: ` - Error if something went wrong publishing the notification otherwise null. -- `block: ` - A block object as seen in the [getBlock](/api/http#getblock) RPC HTTP method. - -```json -{ - "jsonrpc": "2.0", - "method": "blockNotification", - "params": { - "result": { - "context": { - "slot": 112301554 - }, - "value": { - "slot": 112301554, - "block": { - "previousBlockhash": "GJp125YAN4ufCSUvZJVdCyWQJ7RPWMmwxoyUQySydZA", - "blockhash": "6ojMHjctdqfB55JDpEpqfHnP96fiaHEcvzEQ2NNcxzHP", - "parentSlot": 112301553, - "transactions": [ - { - "transaction": [ - "OpltwoUvWxYi1P2U8vbIdE/aPntjYo5Aa0VQ2JJyeJE2g9Vvxk8dDGgFMruYfDu8/IfUWb0REppTe7IpAuuLRgIBAAkWnj4KHRpEWWW7gvO1c0BHy06wZi2g7/DLqpEtkRsThAXIdBbhXCLvltw50ZnjDx2hzw74NVn49kmpYj2VZHQJoeJoYJqaKcvuxCi/2i4yywedcVNDWkM84Iuw+cEn9/ROCrXY4qBFI9dveEERQ1c4kdU46xjxj9Vi+QXkb2Kx45QFVkG4Y7HHsoS6WNUiw2m4ffnMNnOVdF9tJht7oeuEfDMuUEaO7l9JeUxppCvrGk3CP45saO51gkwVYEgKzhpKjCx3rgsYxNR81fY4hnUQXSbbc2Y55FkwgRBpVvQK7/+clR4Gjhd3L4y+OtPl7QF93Akg1LaU9wRMs5nvfDFlggqI9PqJl+IvVWrNRdBbPS8LIIhcwbRTkSbqlJQWxYg3Bo2CTVbw7rt1ZubuHWWp0mD/UJpLXGm2JprWTePNULzHu67sfqaWF99LwmwjTyYEkqkRt1T0Je5VzHgJs0N5jY4iIU9K3lMqvrKOIn/2zEMZ+ol2gdgjshx+sphIyhw65F3J/Dbzk04LLkK+CULmN571Y+hFlXF2ke0BIuUG6AUF+4214Cu7FXnqo3rkxEHDZAk0lRrAJ8X/Z+iwuwI5cgbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV+/wCpDLAp8axcEkaQkLDKRoWxqp8XLNZSKial7Rk+ELAVVKWoWLRXRZ+OIggu0OzMExvVLE5VHqy71FNHq4gGitkiKYNFWSLIE4qGfdFLZXy/6hwS+wq9ewjikCpd//C9BcCL7Wl0iQdUslxNVCBZHnCoPYih9JXvGefOb9WWnjGy14sG9j70+RSVx6BlkFELWwFvIlWR/tHn3EhHAuL0inS2pwX7ZQTAU6gDVaoqbR2EiJ47cKoPycBNvHLoKxoY9AZaBjPl6q8SKQJSFyFd9n44opAgI6zMTjYF/8Ok4VpXEESp3QaoUyTI9sOJ6oFP6f4dwnvQelgXS+AEfAsHsKXxGAIUDQENAgMEBQAGBwgIDg8IBJCER3QXl1AVDBADCQoOAAQLERITDAjb7ugh3gOuTy==", - "base64" - ], - "meta": { - "err": null, - "status": { - "Ok": null - }, - "fee": 5000, - "preBalances": [ - 1758510880, 2067120, 1566000, 1461600, 2039280, 2039280, - 1900080, 1865280, 0, 3680844220, 2039280 - ], - "postBalances": [ - 1758505880, 2067120, 1566000, 1461600, 2039280, 2039280, - 1900080, 1865280, 0, 3680844220, 2039280 - ], - "innerInstructions": [ - { - "index": 0, - "instructions": [ - { - "programIdIndex": 13, - "accounts": [1, 15, 3, 4, 2, 14], - "data": "21TeLgZXNbtHXVBzCaiRmH" - }, - { - "programIdIndex": 14, - "accounts": [3, 4, 1], - "data": "6qfC8ic7Aq99" - }, - { - "programIdIndex": 13, - "accounts": [1, 15, 3, 5, 2, 14], - "data": "21TeLgZXNbsn4QEpaSEr3q" - }, - { - "programIdIndex": 14, - "accounts": [3, 5, 1], - "data": "6LC7BYyxhFRh" - } - ] - }, - { - "index": 1, - "instructions": [ - { - "programIdIndex": 14, - "accounts": [4, 3, 0], - "data": "7aUiLHFjSVdZ" - }, - { - "programIdIndex": 19, - "accounts": [17, 18, 16, 9, 11, 12, 14], - "data": "8kvZyjATKQWYxaKR1qD53V" - }, - { - "programIdIndex": 14, - "accounts": [9, 11, 18], - "data": "6qfC8ic7Aq99" - } - ] - } - ], - "logMessages": [ - "Program QMNeHCGYnLVDn1icRAfQZpjPLBNkfGbSKRB83G5d8KB invoke [1]", - "Program QMWoBmAyJLAsA1Lh9ugMTw2gciTihncciphzdNzdZYV invoke [2]" - ], - "preTokenBalances": [ - { - "accountIndex": 4, - "mint": "iouQcQBAiEXe6cKLS85zmZxUqaCqBdeHFpqKoSz615u", - "uiTokenAmount": { - "uiAmount": null, - "decimals": 6, - "amount": "0", - "uiAmountString": "0" - }, - "owner": "LieKvPRE8XeX3Y2xVNHjKlpAScD12lYySBVQ4HqoJ5op", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" - }, - { - "accountIndex": 5, - "mint": "iouQcQBAiEXe6cKLS85zmZxUqaCqBdeHFpqKoSz615u", - "uiTokenAmount": { - "uiAmount": 11513.0679, - "decimals": 6, - "amount": "11513067900", - "uiAmountString": "11513.0679" - }, - "owner": "rXhAofQCT7NN9TUqigyEAUzV1uLL4boeD8CRkNBSkYk", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" - }, - { - "accountIndex": 10, - "mint": "Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1", - "uiTokenAmount": { - "uiAmount": null, - "decimals": 6, - "amount": "0", - "uiAmountString": "0" - }, - "owner": "CL9wkGFT3SZRRNa9dgaovuRV7jrVVigBUZ6DjcgySsCU", - "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" - }, - { - "accountIndex": 11, - "mint": "Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1", - "uiTokenAmount": { - "uiAmount": 15138.514093, - "decimals": 6, - "amount": "15138514093", - "uiAmountString": "15138.514093" - }, - "owner": "LieKvPRE8XeX3Y2xVNHjKlpAScD12lYySBVQ4HqoJ5op", - "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" - } - ], - "postTokenBalances": [ - { - "accountIndex": 4, - "mint": "iouQcQBAiEXe6cKLS85zmZxUqaCqBdeHFpqKoSz615u", - "uiTokenAmount": { - "uiAmount": null, - "decimals": 6, - "amount": "0", - "uiAmountString": "0" - }, - "owner": "LieKvPRE8XeX3Y2xVNHjKlpAScD12lYySBVQ4HqoJ5op", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" - }, - { - "accountIndex": 5, - "mint": "iouQcQBAiEXe6cKLS85zmZxUqaCqBdeHFpqKoSz615u", - "uiTokenAmount": { - "uiAmount": 11513.103028, - "decimals": 6, - "amount": "11513103028", - "uiAmountString": "11513.103028" - }, - "owner": "rXhAofQCT7NN9TUqigyEAUzV1uLL4boeD8CRkNBSkYk", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" - }, - { - "accountIndex": 10, - "mint": "Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1", - "uiTokenAmount": { - "uiAmount": null, - "decimals": 6, - "amount": "0", - "uiAmountString": "0" - }, - "owner": "CL9wkGFT3SZRRNa9dgaovuRV7jrVVigBUZ6DjcgySsCU", - "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" - }, - { - "accountIndex": 11, - "mint": "Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1", - "uiTokenAmount": { - "uiAmount": 15489.767829, - "decimals": 6, - "amount": "15489767829", - "uiAmountString": "15489.767829" - }, - "owner": "BeiHVPRE8XeX3Y2xVNrSsTpAScH94nYySBVQ4HqgN9at", - "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" - } - ], - "rewards": [] - } - } - ], - "blockTime": 1639926816, - "blockHeight": 101210751 - }, - "err": null - } - }, - "subscription": 14 - } -} -``` - -
    diff --git a/docs/src/api/websocket/_blockUnsubscribe.mdx b/docs/src/api/websocket/_blockUnsubscribe.mdx deleted file mode 100644 index a16b73ca63..0000000000 --- a/docs/src/api/websocket/_blockUnsubscribe.mdx +++ /dev/null @@ -1,53 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## blockUnsubscribe - -Unsubscribe from block notifications - - - - -### Parameters: - - - subscription id to cancel - - -### Result: - -`` - unsubscribe success message - - - - - -### Code sample: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "method": "blockUnsubscribe", - "params": [0] -} -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": true, "id": 1 } -``` - - - - diff --git a/docs/src/api/websocket/_logsSubscribe.mdx b/docs/src/api/websocket/_logsSubscribe.mdx deleted file mode 100644 index 6955004489..0000000000 --- a/docs/src/api/websocket/_logsSubscribe.mdx +++ /dev/null @@ -1,146 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## logsSubscribe - -Subscribe to transaction logging - - - - -### Parameters: - - - filter criteria for the logs to receive results by account type. The following filters types are currently supported: - - - -A string with one of the following values: - -- `all` - subscribe to all transactions except for simple vote transactions -- `allWithVotes` - subscribe to all transactions, including simple vote - transactions - - - - - -An object with the following field: - -- `mentions: [ ]` - array containing a single Pubkey (as base-58 - encoded string); if present, subscribe to only transactions mentioning this address - -:::caution - -Currently, the `mentions` field -[only supports one](https://github.com/solana-labs/solana/blob/master/rpc/src/rpc_pubsub.rs#L481) -Pubkey string per method call. Listing additional addresses will result in an -error. - -::: - - - - - - - -Configuration object containing the following fields: - - - - - -### Result: - -`` - Subscription id \(needed to unsubscribe\) - - - - - -### Code sample: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "method": "logsSubscribe", - "params": [ - { - "mentions": [ "11111111111111111111111111111111" ] - }, - { - "commitment": "finalized" - } - ] -} -{ - "jsonrpc": "2.0", - "id": 1, - "method": "logsSubscribe", - "params": [ "all" ] -} -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 24040, "id": 1 } -``` - - - - -#### Notification Format: - -The notification will be an RpcResponse JSON object with value equal to: - -- `signature: ` - The transaction signature base58 encoded. -- `err: ` - Error if transaction failed, null if transaction - succeeded. - [TransactionError definitions](https://github.com/solana-labs/solana/blob/c0c60386544ec9a9ec7119229f37386d9f070523/sdk/src/transaction/error.rs#L13) -- `logs: ` - Array of log messages the transaction instructions - output during execution, null if simulation failed before the transaction was - able to execute (for example due to an invalid blockhash or signature - verification failure) - -Example: - -```json -{ - "jsonrpc": "2.0", - "method": "logsNotification", - "params": { - "result": { - "context": { - "slot": 5208469 - }, - "value": { - "signature": "5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv", - "err": null, - "logs": [ - "SBF program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri success" - ] - } - }, - "subscription": 24040 - } -} -``` - - diff --git a/docs/src/api/websocket/_logsUnsubscribe.mdx b/docs/src/api/websocket/_logsUnsubscribe.mdx deleted file mode 100644 index 6a75606eb0..0000000000 --- a/docs/src/api/websocket/_logsUnsubscribe.mdx +++ /dev/null @@ -1,53 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## logsUnsubscribe - -Unsubscribe from transaction logging - - - - -### Parameters: - - - subscription id to cancel - - -### Result: - -`` - unsubscribe success message - - - - - -### Code sample: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "method": "logsUnsubscribe", - "params": [0] -} -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": true, "id": 1 } -``` - - - - diff --git a/docs/src/api/websocket/_programSubscribe.mdx b/docs/src/api/websocket/_programSubscribe.mdx deleted file mode 100644 index bea83bac6c..0000000000 --- a/docs/src/api/websocket/_programSubscribe.mdx +++ /dev/null @@ -1,205 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## programSubscribe - -Subscribe to a program to receive notifications when the lamports or data for an account owned by the given program changes - - - - -### Parameters: - - - -Pubkey of the `program_id`, as base-58 encoded string - - - - - -Configuration object containing the following fields: - - - - - -filter results using various [filter objects](/api/http#filter-criteria) - -:::info -The resultant account must meet **ALL** filter criteria to be included in the returned results -::: - - - - - -Encoding format for Account data - - - -
    - -- `base58` is slow. -- [`jsonParsed`](/api/http#parsed-responses">) encoding attempts to use program-specific - state parsers to return more human-readable and explicit account state data. -- If `jsonParsed` is requested but a parser cannot be found, the field falls - back to `base64` encoding, detectable when the `data` field is type `string`. - -
    - -
    - -
    - -### Result: - -`` - Subscription id \(needed to unsubscribe\) - -
    - - - -### Code sample: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "method": "programSubscribe", - "params": [ - "11111111111111111111111111111111", - { - "encoding": "base64", - "commitment": "finalized" - } - ] -} -{ - "jsonrpc": "2.0", - "id": 1, - "method": "programSubscribe", - "params": [ - "11111111111111111111111111111111", - { - "encoding": "jsonParsed" - } - ] -} -{ - "jsonrpc": "2.0", - "id": 1, - "method": "programSubscribe", - "params": [ - "11111111111111111111111111111111", - { - "encoding": "base64", - "filters": [ - { - "dataSize": 80 - } - ] - } - ] -} -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 24040, "id": 1 } -``` - - -
    - -#### Notification format - -The notification format is a single program account object as seen in the [getProgramAccounts](/api/http#getprogramaccounts) RPC HTTP method. - -Base58 encoding: - -```json -{ - "jsonrpc": "2.0", - "method": "programNotification", - "params": { - "result": { - "context": { - "slot": 5208469 - }, - "value": { - "pubkey": "H4vnBqifaSACnKa7acsxstsY1iV1bvJNxsCY7enrd1hq", - "account": { - "data": [ - "11116bv5nS2h3y12kD1yUKeMZvGcKLSjQgX6BeV7u1FrjeJcKfsHPXHRDEHrBesJhZyqnnq9qJeUuF7WHxiuLuL5twc38w2TXNLxnDbjmuR", - "base58" - ], - "executable": false, - "lamports": 33594, - "owner": "11111111111111111111111111111111", - "rentEpoch": 636, - "space": 80 - } - } - }, - "subscription": 24040 - } -} -``` - -Parsed-JSON encoding: - -```json -{ - "jsonrpc": "2.0", - "method": "programNotification", - "params": { - "result": { - "context": { - "slot": 5208469 - }, - "value": { - "pubkey": "H4vnBqifaSACnKa7acsxstsY1iV1bvJNxsCY7enrd1hq", - "account": { - "data": { - "program": "nonce", - "parsed": { - "type": "initialized", - "info": { - "authority": "Bbqg1M4YVVfbhEzwA9SpC9FhsaG83YMTYoR4a8oTDLX", - "blockhash": "LUaQTmM7WbMRiATdMMHaRGakPtCkc2GHtH57STKXs6k", - "feeCalculator": { - "lamportsPerSignature": 5000 - } - } - } - }, - "executable": false, - "lamports": 33594, - "owner": "11111111111111111111111111111111", - "rentEpoch": 636, - "space": 80 - } - } - }, - "subscription": 24040 - } -} -``` - -
    diff --git a/docs/src/api/websocket/_programUnsubscribe.mdx b/docs/src/api/websocket/_programUnsubscribe.mdx deleted file mode 100644 index b3decdcb9a..0000000000 --- a/docs/src/api/websocket/_programUnsubscribe.mdx +++ /dev/null @@ -1,53 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## programUnsubscribe - -Unsubscribe from program-owned account change notifications - - - - -### Parameters: - - - id of account Subscription to cancel - - -### Result: - -`` - unsubscribe success message - - - - - -### Code sample: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "method": "programUnsubscribe", - "params": [0] -} -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": true, "id": 1 } -``` - - - - diff --git a/docs/src/api/websocket/_rootSubscribe.mdx b/docs/src/api/websocket/_rootSubscribe.mdx deleted file mode 100644 index 98fd59407f..0000000000 --- a/docs/src/api/websocket/_rootSubscribe.mdx +++ /dev/null @@ -1,62 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## rootSubscribe - -Subscribe to receive notification anytime a new root is set by the validator. - - - - -### Parameters: - -**None** - -### Result: - -`integer` - subscription id \(needed to unsubscribe\) - - - - - -### Code sample: - -```json -{ "jsonrpc": "2.0", "id": 1, "method": "rootSubscribe" } -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 0, "id": 1 } -``` - - - - -#### Notification Format: - -The result is the latest root slot number. - -```json -{ - "jsonrpc": "2.0", - "method": "rootNotification", - "params": { - "result": 42, - "subscription": 0 - } -} -``` - - diff --git a/docs/src/api/websocket/_rootUnsubscribe.mdx b/docs/src/api/websocket/_rootUnsubscribe.mdx deleted file mode 100644 index 8d4085f183..0000000000 --- a/docs/src/api/websocket/_rootUnsubscribe.mdx +++ /dev/null @@ -1,53 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## rootUnsubscribe - -Unsubscribe from root notifications - - - - -### Parameters: - - - subscription id to cancel - - -### Result: - -`` - unsubscribe success message - - - - - -### Code sample: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "method": "rootUnsubscribe", - "params": [0] -} -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": true, "id": 1 } -``` - - - - diff --git a/docs/src/api/websocket/_signatureSubscribe.mdx b/docs/src/api/websocket/_signatureSubscribe.mdx deleted file mode 100644 index 1c0d8f58fc..0000000000 --- a/docs/src/api/websocket/_signatureSubscribe.mdx +++ /dev/null @@ -1,160 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## signatureSubscribe - -Subscribe to receive a notification when the transaction with the given -signature reaches the specified commitment level. - -:::caution - -This is a subscription to a single notification. It is automatically cancelled -by the server once the notification, `signatureNotification`, is sent by the -RPC. - -::: - - - - -### Parameters: - - - -transaction signature, as base-58 encoded string - -:::info - -The transaction signature must be the first signature from the transaction (see -[transaction id](/terminology#transaction-id) for more details). - -::: - - - - - -Configuration object containing the following fields: - - - - - -Whether or not to subscribe for notifications when signatures are received by -the RPC, in addition to when they are processed. - - - - - -### Result: - -`` - subscription id (needed to unsubscribe) - - - - - -### Code sample: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "method": "signatureSubscribe", - "params": [ - "2EBVM6cB8vAAD93Ktr6Vd8p67XPbQzCJX47MpReuiCXJAtcjaxpvWpcg9Ege1Nr5Tk3a2GFrByT7WPBjdsTycY9b", - { - "commitment": "finalized", - "enableReceivedNotification": false - } - ] -} -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 0, "id": 1 } -``` - - - - -#### Notification Format: - -The notification will be an RpcResponse JSON object with value containing an -object with: - -- `slot: ` - The corresponding slot. -- `value: ` - a notification value of - [`RpcSignatureResult`](https://github.com/solana-labs/solana/blob/6d28fd455b07e3557fc6c0c3ddf3ba03e3fe8482/rpc-client-api/src/response.rs#L265-L268), - resulting in either: - - when `enableReceivedNotification` is `true` and the signature is received: the - literal string - [`"receivedSignature"`](https://github.com/solana-labs/solana/blob/6d28fd455b07e3557fc6c0c3ddf3ba03e3fe8482/rpc-client-api/src/response.rs#L286-L288), - or - - when the signature is processed: `err: `: - - `null` if the transaction succeeded in being processed at the specified - commitment level, or - - a - [`TransactionError`](https://github.com/solana-labs/solana/blob/6d28fd455b07e3557fc6c0c3ddf3ba03e3fe8482/sdk/src/transaction/error.rs#L15-L164), - if the transaction failed - -#### Example responses: - -The following is an example response of a notification from a successfully -**processed** transactions: - -```json -{ - "jsonrpc": "2.0", - "method": "signatureNotification", - "params": { - "result": { - "context": { - "slot": 5207624 - }, - "value": { - "err": null - } - }, - "subscription": 24006 - } -} -``` - -The following is an example response of a notification from a successfully -**recieved** transaction signature: - -```json -{ - "jsonrpc": "2.0", - "method": "signatureNotification", - "params": { - "result": { - "context": { - "slot": 5207624 - }, - "value": "receivedSignature" - }, - "subscription": 24006 - } -} -``` - - diff --git a/docs/src/api/websocket/_signatureUnsubscribe.mdx b/docs/src/api/websocket/_signatureUnsubscribe.mdx deleted file mode 100644 index 880efed7c4..0000000000 --- a/docs/src/api/websocket/_signatureUnsubscribe.mdx +++ /dev/null @@ -1,53 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## signatureUnsubscribe - -Unsubscribe from signature confirmation notification - - - - -### Parameters: - - - subscription id to cancel - - -### Result: - -`` - unsubscribe success message - - - - - -### Code sample: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "method": "signatureUnsubscribe", - "params": [0] -} -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": true, "id": 1 } -``` - - - - diff --git a/docs/src/api/websocket/_slotSubscribe.mdx b/docs/src/api/websocket/_slotSubscribe.mdx deleted file mode 100644 index c746ff060e..0000000000 --- a/docs/src/api/websocket/_slotSubscribe.mdx +++ /dev/null @@ -1,72 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## slotSubscribe - -Subscribe to receive notification anytime a slot is processed by the validator - - - - -### Parameters: - -**None** - -### Result: - -`` - Subscription id \(needed to unsubscribe\) - - - - - -### Code sample: - -```json -{ "jsonrpc": "2.0", "id": 1, "method": "slotSubscribe" } -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 0, "id": 1 } -``` - - - - -#### Notification Format: - -The notification will be an object with the following fields: - -- `parent: ` - The parent slot -- `root: ` - The current root slot -- `slot: ` - The newly set slot value - -Example: - -```json -{ - "jsonrpc": "2.0", - "method": "slotNotification", - "params": { - "result": { - "parent": 75, - "root": 44, - "slot": 76 - }, - "subscription": 0 - } -} -``` - - diff --git a/docs/src/api/websocket/_slotUnsubscribe.mdx b/docs/src/api/websocket/_slotUnsubscribe.mdx deleted file mode 100644 index 0ce506163c..0000000000 --- a/docs/src/api/websocket/_slotUnsubscribe.mdx +++ /dev/null @@ -1,53 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## slotUnsubscribe - -Unsubscribe from slot notifications - - - - -### Parameters: - - - subscription id to cancel - - -### Result: - -`` - unsubscribe success message - - - - - -### Code sample: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "method": "slotUnsubscribe", - "params": [0] -} -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": true, "id": 1 } -``` - - - - diff --git a/docs/src/api/websocket/_slotsUpdatesSubscribe.mdx b/docs/src/api/websocket/_slotsUpdatesSubscribe.mdx deleted file mode 100644 index cbd6a6aec1..0000000000 --- a/docs/src/api/websocket/_slotsUpdatesSubscribe.mdx +++ /dev/null @@ -1,92 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## slotsUpdatesSubscribe - -Subscribe to receive a notification from the validator on a variety of updates -on every slot - -:::caution -This subscription is unstable - -**NOTE: the format of this subscription may change in the future and it may not always be supported** -::: - - - - -### Parameters: - -**None** - -### Result: - -`` - Subscription id (needed to unsubscribe) - - - - - -### Code sample: - -```json -{ "jsonrpc": "2.0", "id": 1, "method": "slotsUpdatesSubscribe" } -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 0, "id": 1 } -``` - - - - -#### Notification Format: - -The notification will be an object with the following fields: - -- `err: ` - The error message. Only present if the update is of type "dead". -- `parent: ` - The parent slot. Only present if the update is of type "createdBank". -- `slot: ` - The newly updated slot -- `stats: ` - The error message. Only present if the update is of type "frozen". An object with the following fields: - - `maxTransactionsPerEntry: `, - - `numFailedTransactions: `, - - `numSuccessfulTransactions: `, - - `numTransactionEntries: `, -- `timestamp: ` - The Unix timestamp of the update -- `type: ` - The update type, one of: - - "firstShredReceived" - - "completed" - - "createdBank" - - "frozen" - - "dead" - - "optimisticConfirmation" - - "root" - -```bash -{ - "jsonrpc": "2.0", - "method": "slotsUpdatesNotification", - "params": { - "result": { - "parent": 75, - "slot": 76, - "timestamp": 1625081266243, - "type": "optimisticConfirmation" - }, - "subscription": 0 - } -} -``` - - diff --git a/docs/src/api/websocket/_slotsUpdatesUnsubscribe.mdx b/docs/src/api/websocket/_slotsUpdatesUnsubscribe.mdx deleted file mode 100644 index 8169e52118..0000000000 --- a/docs/src/api/websocket/_slotsUpdatesUnsubscribe.mdx +++ /dev/null @@ -1,53 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## slotsUpdatesUnsubscribe - -Unsubscribe from slot-update notifications - - - - -### Parameters: - - - subscription id to cancel - - -### Result: - -`` - unsubscribe success message - - - - - -### Code sample: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "method": "slotsUpdatesUnsubscribe", - "params": [0] -} -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": true, "id": 1 } -``` - - - - diff --git a/docs/src/api/websocket/_voteSubscribe.mdx b/docs/src/api/websocket/_voteSubscribe.mdx deleted file mode 100644 index d100035d93..0000000000 --- a/docs/src/api/websocket/_voteSubscribe.mdx +++ /dev/null @@ -1,80 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## voteSubscribe - -Subscribe to receive notification anytime a new vote is observed in gossip. -These votes are pre-consensus therefore there is no guarantee these votes will -enter the ledger. - -:::caution -This subscription is unstable and only available if the validator was started -with the `--rpc-pubsub-enable-vote-subscription` flag. The format of this -subscription may change in the future -::: - - - - -### Parameters: - -**None** - -### Result: - -`` - subscription id (needed to unsubscribe) - - - - - -### Code sample: - -```json -{ "jsonrpc": "2.0", "id": 1, "method": "voteSubscribe" } -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": 0, "id": 1 } -``` - - - - -#### Notification Format: - -The notification will be an object with the following fields: - -- `hash: ` - The vote hash -- `slots: ` - The slots covered by the vote, as an array of u64 integers -- `timestamp: ` - The timestamp of the vote -- `signature: ` - The signature of the transaction that contained this vote -- `votePubkey: ` - The public key of the vote account, as base-58 encoded string - -```json -{ - "jsonrpc": "2.0", - "method": "voteNotification", - "params": { - "result": { - "hash": "8Rshv2oMkPu5E4opXTRyuyBeZBqQ4S477VG26wUTFxUM", - "slots": [1, 2], - "timestamp": null - }, - "subscription": 0 - } -} -``` - - diff --git a/docs/src/api/websocket/_voteUnsubscribe.mdx b/docs/src/api/websocket/_voteUnsubscribe.mdx deleted file mode 100644 index db37b42054..0000000000 --- a/docs/src/api/websocket/_voteUnsubscribe.mdx +++ /dev/null @@ -1,53 +0,0 @@ -import { - DocBlock, - DocSideBySide, - CodeParams, - Parameter, - Field, - Values, - CodeSnippets, -} from "../../../components/CodeDocBlock"; - - - -## voteUnsubscribe - -Unsubscribe from vote notifications - - - - -### Parameters: - - - subscription id to cancel - - -### Result: - -`` - unsubscribe success message - - - - - -### Code sample: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "method": "voteUnsubscribe", - "params": [0] -} -``` - -### Response: - -```json -{ "jsonrpc": "2.0", "result": true, "id": 1 } -``` - - - - diff --git a/docs/src/architecture.md b/docs/src/architecture.md new file mode 100644 index 0000000000..3ba64f2d80 --- /dev/null +++ b/docs/src/architecture.md @@ -0,0 +1,7 @@ +--- +title: Architecture +sidebar_label: Overview +sidebar_position: 0 +--- + +In this section, we will describe the architecture. diff --git a/docs/src/developing/backwards-compatibility.md b/docs/src/backwards-compatibility.md similarity index 100% rename from docs/src/developing/backwards-compatibility.md rename to docs/src/backwards-compatibility.md diff --git a/docs/src/cli/.usage.md.header b/docs/src/cli/.usage.md.header index 4c532f9ebf..9ee41c132f 100644 --- a/docs/src/cli/.usage.md.header +++ b/docs/src/cli/.usage.md.header @@ -1,5 +1,7 @@ --- -title: CLI Usage Reference +title: Solana CLI Reference and Usage +sidebar_label: Reference & Usage +sidebar_position: 3 --- The [solana-cli crate](https://crates.io/crates/solana-cli) provides a command-line interface tool for Solana diff --git a/docs/src/cli/examples/_category_.json b/docs/src/cli/examples/_category_.json new file mode 100644 index 0000000000..9a1a43e307 --- /dev/null +++ b/docs/src/cli/examples/_category_.json @@ -0,0 +1,7 @@ +{ + "position": 4.5, + "label": "Command Examples", + "collapsible": true, + "collapsed": false, + "link": null +} diff --git a/docs/src/cli/choose-a-cluster.md b/docs/src/cli/examples/choose-a-cluster.md similarity index 91% rename from docs/src/cli/choose-a-cluster.md rename to docs/src/cli/examples/choose-a-cluster.md index cf10c1f190..b7c51ffc73 100644 --- a/docs/src/cli/choose-a-cluster.md +++ b/docs/src/cli/examples/choose-a-cluster.md @@ -2,7 +2,7 @@ title: Connecting to a Cluster --- -See [Solana Clusters](../clusters.md) for general information about the +See [Solana Clusters](../../clusters/available.md) for general information about the available clusters. ## Configure the command-line tool diff --git a/docs/src/cli/delegate-stake.md b/docs/src/cli/examples/delegate-stake.md similarity index 77% rename from docs/src/cli/delegate-stake.md rename to docs/src/cli/examples/delegate-stake.md index 093c3e2ccf..03d0465eef 100644 --- a/docs/src/cli/delegate-stake.md +++ b/docs/src/cli/examples/delegate-stake.md @@ -1,24 +1,26 @@ --- title: Staking --- + For an overview of staking, read first the [Staking and Inflation FAQ](https://solana.com/staking). ------- +--- -After you have [received SOL](transfer-tokens.md), you might consider putting -it to use by delegating _stake_ to a validator. Stake is what we call tokens -in a _stake account_. Solana weights validator votes by the amount of stake -delegated to them, which gives those validators more influence in determining -then next valid block of transactions in the blockchain. Solana then generates -new SOL periodically to reward stakers and validators. You earn more rewards -the more stake you delegate. +After you have [received SOL](./transfer-tokens.md), you might consider putting it +to use by delegating _stake_ to a validator. Stake is what we call tokens in a +_stake account_. Solana weights validator votes by the amount of stake delegated +to them, which gives those validators more influence in determining then next +valid block of transactions in the blockchain. Solana then generates new SOL +periodically to reward stakers and validators. You earn more rewards the more +stake you delegate. ## Create a Stake Account To delegate stake, you will need to transfer some tokens into a stake account. To create an account, you will need a keypair. Its public key will be used as -the [stake account address](../staking/stake-accounts.md#account-address). +the +[stake account address](https://solana.com/docs/economics/staking/stake-accounts#account-address). No need for a password or encryption here; this keypair will be discarded right after creating the stake account. @@ -67,11 +69,10 @@ Withdraw Authority: EXU95vqs93yPeCeAU7mPPu6HbRUmTFPEiGug9oCdvQ5F ### Set Stake and Withdraw Authorities -[Stake and withdraw authorities](../staking/stake-accounts.md#understanding-account-authorities) -can be set when creating an account via the -`--stake-authority` and `--withdraw-authority` options, or afterward with the -`solana stake-authorize` command. For example, to set a new stake authority, -run: +[Stake and withdraw authorities](https://solana.com/docs/economics/staking/stake-accounts#understanding-account-authorities) +can be set when creating an account via the `--stake-authority` and +`--withdraw-authority` options, or afterward with the `solana stake-authorize` +command. For example, to set a new stake authority, run: ```bash solana stake-authorize \ @@ -95,11 +96,12 @@ solana create-stake-account --from --seed --withdraw-authority --fee-payer ``` -`` is an arbitrary string up to 32 bytes, but will typically be a -number corresponding to which derived account this is. The first account might -be "0", then "1", and so on. The public key of `` acts -as the base address. The command derives a new address from the base address -and seed string. To see what stake address the command will derive, use `solana create-address-with-seed`: +`` is an arbitrary string up to 32 bytes, but will typically be a number +corresponding to which derived account this is. The first account might be "0", +then "1", and so on. The public key of `` acts as the +base address. The command derives a new address from the base address and seed +string. To see what stake address the command will derive, use +`solana create-address-with-seed`: ```bash solana create-address-with-seed --from STAKE @@ -121,9 +123,9 @@ accounts with the `solana validators` command: solana validators ``` -The first column of each row contains the validator's identity and the second -is the vote account address. Choose a validator and use its vote account -address in `solana delegate-stake`: +The first column of each row contains the validator's identity and the second is +the vote account address. Choose a validator and use its vote account address in +`solana delegate-stake`: ```bash solana delegate-stake --stake-authority \ @@ -134,8 +136,8 @@ The stake authority `` authorizes the operation on the account with address ``. The stake is delegated to the vote account with address ``. -After delegating stake, use `solana stake-account` to observe the changes -to the stake account: +After delegating stake, use `solana stake-account` to observe the changes to the +stake account: ```bash solana stake-account @@ -164,8 +166,8 @@ solana deactivate-stake --stake-authority \ --fee-payer ``` -The stake authority `` authorizes the operation on the account -with address ``. +The stake authority `` authorizes the operation on the account with +address ``. Note that stake takes several epochs to "cool down". Attempts to delegate stake in the cool down period will fail. @@ -180,8 +182,8 @@ solana withdraw-stake --withdraw-authority ` is the existing stake account, the stake authority -`` is the withdraw authority, and `` is the number of tokens -to transfer to ``. +`` is the withdraw authority, and `` is the number of tokens to +transfer to ``. ## Split Stake @@ -196,11 +198,11 @@ solana split-stake --stake-authority ` is the existing stake account, the stake authority -`` is the stake authority, `` is the -keypair for the new account, and `` is the number of tokens to transfer -to the new account. +`` is the stake authority, `` is the keypair +for the new account, and `` is the number of tokens to transfer to the +new account. To split a stake account into a derived account address, use the `--seed` option. See -[Derive Stake Account Addresses](#advanced-derive-stake-account-addresses) -for details. +[Derive Stake Account Addresses](#advanced-derive-stake-account-addresses) for +details. diff --git a/docs/src/cli/deploy-a-program.md b/docs/src/cli/examples/deploy-a-program.md similarity index 83% rename from docs/src/cli/deploy-a-program.md rename to docs/src/cli/examples/deploy-a-program.md index 333d07946f..755d165f4b 100644 --- a/docs/src/cli/deploy-a-program.md +++ b/docs/src/cli/examples/deploy-a-program.md @@ -2,18 +2,21 @@ title: Deploy a Program --- -Developers can deploy on-chain [programs](terminology.md#program) (often called -smart contracts elsewhere) with the Solana tools. +Developers can deploy on-chain +[programs](https://solana.com/docs/terminology#program) (often called smart +contracts elsewhere) with the Solana tools. To learn about developing and executing programs on Solana, start with the -[intro to Solana programs](developing/intro/programs.md) and then dig into the -details of [on-chain programs](developing/on-chain-programs/overview.md). +[intro to Solana programs](https://solana.com/docs/core/programs) and then dig +into the details of +[developing on-chain programs](https://solana.com/docs/programs). To deploy a program, use the Solana tools to interact with the on-chain loader to: - Initialize a program account -- Upload the program's shared object (the program binary `.so`) to the program account's data buffer +- Upload the program's shared object (the program binary `.so`) to the program + account's data buffer - (optional) Verify the uploaded program - Finalize the program by marking the program account executable. @@ -89,8 +92,8 @@ Data Length: 5216 (0x1460) bytes ### Redeploy a program A program can be redeployed to the same address to facilitate rapid development, -bug fixes, or upgrades. If a program id is not provided, the program will be -deployed to the default address at `-keypair.json`. This default +bug fixes, or upgrades. If a program id is not provided, the program will be +deployed to the default address at `-keypair.json`. This default keypair is generated during the first program compilation. The command looks the same as the deployment command: @@ -101,10 +104,10 @@ solana program deploy By default, programs are deployed to accounts that are twice the size of the original deployment. Doing so leaves room for program growth in future -redeployments. But, if the initially deployed program is very small and then -later grows substantially, the redeployment may fail. To avoid this, specify -a `max_len` that is at least the size (in bytes) that the program is expected -to become (plus some wiggle room). +redeployments. But, if the initially deployed program is very small and then +later grows substantially, the redeployment may fail. To avoid this, specify a +`max_len` that is at least the size (in bytes) that the program is expected to +become (plus some wiggle room). ```bash solana program deploy --max-len 200000 @@ -113,9 +116,9 @@ solana program deploy --max-len 200000 ### Resuming a failed deploy If program deployment fails, there will be a hanging intermediate buffer account -that contains a non-zero balance. In order to recoup that balance you may -resume a failed deployment by providing the same intermediate buffer to a new -call to `deploy`. +that contains a non-zero balance. In order to recoup that balance you may resume +a failed deployment by providing the same intermediate buffer to a new call to +`deploy`. Deployment failures will print an error message specifying the seed phrase needed to recover the generated intermediate buffer's keypair: @@ -154,8 +157,8 @@ Both program and buffer accounts can be closed and their lamport balances transferred to a recipient's account. If deployment fails there will be a left-over buffer account that holds -lamports. The buffer account can either be used to [resume a -deploy](#resuming-a-failed-deploy) or closed. +lamports. The buffer account can either be used to +[resume a deploy](#resuming-a-failed-deploy) or closed. The program or buffer account's authority must be present to close an account, to list all the open program or buffer accounts that match the default @@ -228,10 +231,11 @@ Or after deployment and specifying the current authority: solana program set-upgrade-authority --upgrade-authority --new-upgrade-authority ``` -By default, `set-upgrade-authority` requires a signature from the new authority. This behavior prevents a -developer from giving upgrade authority to a key that they do not have access to. The -`--skip-new-upgrade-authority-signer-check` option relaxes the signer check. This can be useful for situations -where the new upgrade authority is an offline signer or a multisig. +By default, `set-upgrade-authority` requires a signature from the new authority. +This behavior prevents a developer from giving upgrade authority to a key that +they do not have access to. The `--skip-new-upgrade-authority-signer-check` +option relaxes the signer check. This can be useful for situations where the new +upgrade authority is an offline signer or a multisig. ### Immutable programs @@ -257,12 +261,12 @@ solana program dump ``` The dumped file will be in the same as what was deployed, so in the case of a -shared object (the program binary `.so`), the dumped file will be a fully functional shared object. Note -that the `dump` command dumps the entire data space, which means the output file -will have trailing zeros after the shared object's data up to `max_len`. -Sometimes it is useful to dump and compare a program to ensure it matches a -known program binary. The dumped file can be zero-truncated, hashed, -and compared to the hash of the original program file. +shared object (the program binary `.so`), the dumped file will be a fully +functional shared object. Note that the `dump` command dumps the entire data +space, which means the output file will have trailing zeros after the shared +object's data up to `max_len`. Sometimes it is useful to dump and compare a +program to ensure it matches a known program binary. The dumped file can be +zero-truncated, hashed, and compared to the hash of the original program file. ```bash $ solana dump dump.so @@ -274,9 +278,10 @@ $ sha256sum extended.so dump.so ### Using an intermediary Buffer account Instead of deploying directly to the program account, the program can be written -to an intermediary buffer account. Intermediary accounts can be useful for things -like multi-entity governed programs where the governing members fist verify the -intermediary buffer contents and then vote to allow an upgrade using it. +to an intermediary buffer account. Intermediary accounts can be useful for +things like multi-entity governed programs where the governing members fist +verify the intermediary buffer contents and then vote to allow an upgrade using +it. ```bash solana program write-buffer @@ -308,8 +313,9 @@ the program: solana program deploy --program-id --buffer ``` -Note, the buffer's authority must match the program's upgrade authority. -During deployment, the buffer account's contents are copied into the program-data account and -the buffer account is set to zero. The lamports from the buffer account are refunded to a spill account. +Note, the buffer's authority must match the program's upgrade authority. During +deployment, the buffer account's contents are copied into the program-data +account and the buffer account is set to zero. The lamports from the buffer +account are refunded to a spill account. Buffers also support `show` and `dump` just like programs do. diff --git a/docs/src/offline-signing/durable-nonce.md b/docs/src/cli/examples/durable-nonce.md similarity index 79% rename from docs/src/offline-signing/durable-nonce.md rename to docs/src/cli/examples/durable-nonce.md index be412b965e..7f0199b8d4 100644 --- a/docs/src/offline-signing/durable-nonce.md +++ b/docs/src/cli/examples/durable-nonce.md @@ -2,15 +2,16 @@ title: Durable Transaction Nonces --- -Durable transaction nonces are a mechanism for getting around the typical -short lifetime of a transaction's [`recent_blockhash`](developing/programming-model/transactions.md#recent-blockhash). +Durable transaction nonces are a mechanism for getting around the typical short +lifetime of a transaction's +[`recent_blockhash`](https://solana.com/docs/core/transactions#recent-blockhash). They are implemented as a Solana Program, the mechanics of which can be read -about in the [proposal](../implemented-proposals/durable-tx-nonces.md). +about in the [proposal](../../implemented-proposals/durable-tx-nonces.md). ## Usage Examples Full usage details for durable nonce CLI commands can be found in the -[CLI reference](../cli/usage.md). +[CLI reference](../usage.md). ### Nonce Authority @@ -18,9 +19,9 @@ Authority over a nonce account can optionally be assigned to another account. In doing so the new authority inherits full control over the nonce account from the previous authority, including the account creator. This feature enables the creation of more complex account ownership arrangements and derived account -addresses not associated with a keypair. The `--nonce-authority ` -argument is used to specify this account and is supported by the following -commands +addresses not associated with a keypair. The +`--nonce-authority ` argument is used to specify this account +and is supported by the following commands - `create-nonce-account` - `new-nonce` @@ -30,10 +31,12 @@ commands ### Nonce Account Creation The durable transaction nonce feature uses an account to store the next nonce -value. Durable nonce accounts must be [rent-exempt](../implemented-proposals/rent.md#two-tiered-rent-regime), -so need to carry the minimum balance to achieve this. +value. Durable nonce accounts must be +[rent-exempt](../../implemented-proposals/rent.md#two-tiered-rent-regime), so need +to carry the minimum balance to achieve this. -A nonce account is created by first generating a new keypair, then create the account on chain +A nonce account is created by first generating a new keypair, then create the +account on chain - Command @@ -48,9 +51,11 @@ solana create-nonce-account nonce-keypair.json 1 2SymGjGV4ksPdpbaqWFiDoBz8okvtiik4KE9cnMQgRHrRLySSdZ6jrEcpPifW4xUpp4z66XM9d9wM48sA7peG2XL ``` -> To keep the keypair entirely offline, use the [Paper Wallet](wallet-guide/paper-wallet.md) keypair generation [instructions](wallet-guide/paper-wallet.md#seed-phrase-generation) instead +> To keep the keypair entirely offline, use the +> [Paper Wallet](../wallets/paper.md) keypair generation +> [instructions](../wallets/paper.md#seed-phrase-generation) instead -> [Full usage documentation](../cli/usage.md#solana-create-nonce-account) +> [Full usage documentation](../usage.md#solana-create-nonce-account) ### Querying the Stored Nonce Value @@ -70,7 +75,7 @@ solana nonce nonce-keypair.json 8GRipryfxcsxN8mAGjy8zbFo9ezaUsh47TsPzmZbuytU ``` -> [Full usage documentation](../cli/usage.md#solana-get-nonce) +> [Full usage documentation](../usage.md#solana-get-nonce) ### Advancing the Stored Nonce Value @@ -89,7 +94,7 @@ solana new-nonce nonce-keypair.json 44jYe1yPKrjuYDmoFTdgPjg8LFpYyh1PFKJqm5SC1PiSyAL8iw1bhadcAX1SL7KDmREEkmHpYvreKoNv6fZgfvUK ``` -> [Full usage documentation](../cli/usage.md#solana-new-nonce) +> [Full usage documentation](../usage.md#solana-new-nonce) ### Display Nonce Account @@ -109,7 +114,7 @@ minimum balance required: 0.00136416 SOL nonce: DZar6t2EaCFQTbUP4DHKwZ1wT8gCPW2aRfkVWhydkBvS ``` -> [Full usage documentation](../cli/usage.md#solana-nonce-account) +> [Full usage documentation](../usage.md#solana-nonce-account) ### Withdraw Funds from a Nonce Account @@ -129,7 +134,7 @@ solana withdraw-from-nonce-account nonce-keypair.json ~/.config/solana/id.json 0 > Close a nonce account by withdrawing the full balance -> [Full usage documentation](../cli/usage.md#solana-withdraw-from-nonce-account) +> [Full usage documentation](../usage.md#solana-withdraw-from-nonce-account) ### Assign a New Authority to a Nonce Account @@ -147,7 +152,7 @@ solana authorize-nonce-account nonce-keypair.json nonce-authority.json 3F9cg4zN9wHxLGx4c3cUKmqpej4oa67QbALmChsJbfxTgTffRiL3iUehVhR9wQmWgPua66jPuAYeL1K2pYYjbNoT ``` -> [Full usage documentation](../cli/usage.md#solana-authorize-nonce-account) +> [Full usage documentation](../usage.md#solana-authorize-nonce-account) ## Other Commands Supporting Durable Nonces @@ -159,9 +164,9 @@ supported. The following subcommands have received this treatment so far -- [`pay`](../cli/usage.md#solana-pay) -- [`delegate-stake`](../cli/usage.md#solana-delegate-stake) -- [`deactivate-stake`](../cli/usage.md#solana-deactivate-stake) +- [`pay`](../usage.md#solana-pay) +- [`delegate-stake`](../usage.md#solana-delegate-stake) +- [`deactivate-stake`](../usage.md#solana-deactivate-stake) ### Example Pay Using Durable Nonce @@ -192,7 +197,8 @@ $ solana airdrop -k alice.json 1 Now Alice needs a nonce account. Create one -> Here, no separate [nonce authority](#nonce-authority) is employed, so `alice.json` has full authority over the nonce account +> Here, no separate [nonce authority](#nonce-authority) is employed, so +> `alice.json` has full authority over the nonce account ```bash $ solana create-nonce-account -k alice.json nonce.json 0.1 @@ -215,7 +221,8 @@ Error: Io(Custom { kind: Other, error: "Transaction \"33gQQaoPc9jWePMvDAeyJpcnSP Alice retries the transaction, this time specifying her nonce account and the blockhash stored there -> Remember, `alice.json` is the [nonce authority](#nonce-authority) in this example +> Remember, `alice.json` is the [nonce authority](#nonce-authority) in this +> example ```bash $ solana nonce-account nonce.json diff --git a/docs/src/offline-signing.md b/docs/src/cli/examples/offline-signing.md similarity index 77% rename from docs/src/offline-signing.md rename to docs/src/cli/examples/offline-signing.md index 5062f0b6a0..8b9312853a 100644 --- a/docs/src/offline-signing.md +++ b/docs/src/cli/examples/offline-signing.md @@ -8,7 +8,7 @@ include: - Collecting signatures from geographically disparate signers in a [multi-signature scheme](https://spl.solana.com/token#multisig-usage) -- Signing transactions using an [airgapped]() +- Signing transactions using an [air-gapped]() signing device This document describes using Solana's CLI to separately sign and submit a @@ -18,26 +18,26 @@ transaction. At present, the following commands support offline signing: -- [`create-stake-account`](cli/usage.md#solana-create-stake-account) -- [`create-stake-account-checked`](cli/usage.md#solana-create-stake-account-checked) -- [`deactivate-stake`](cli/usage.md#solana-deactivate-stake) -- [`delegate-stake`](cli/usage.md#solana-delegate-stake) -- [`split-stake`](cli/usage.md#solana-split-stake) -- [`stake-authorize`](cli/usage.md#solana-stake-authorize) -- [`stake-authorize-checked`](cli/usage.md#solana-stake-authorize-checked) -- [`stake-set-lockup`](cli/usage.md#solana-stake-set-lockup) -- [`stake-set-lockup-checked`](cli/usage.md#solana-stake-set-lockup-checked) -- [`transfer`](cli/usage.md#solana-transfer) -- [`withdraw-stake`](cli/usage.md#solana-withdraw-stake) +- [`create-stake-account`](../usage.md#solana-create-stake-account) +- [`create-stake-account-checked`](../usage.md#solana-create-stake-account-checked) +- [`deactivate-stake`](../usage.md#solana-deactivate-stake) +- [`delegate-stake`](../usage.md#solana-delegate-stake) +- [`split-stake`](../usage.md#solana-split-stake) +- [`stake-authorize`](../usage.md#solana-stake-authorize) +- [`stake-authorize-checked`](../usage.md#solana-stake-authorize-checked) +- [`stake-set-lockup`](../usage.md#solana-stake-set-lockup) +- [`stake-set-lockup-checked`](../usage.md#solana-stake-set-lockup-checked) +- [`transfer`](../usage.md#solana-transfer) +- [`withdraw-stake`](../usage.md#solana-withdraw-stake) -- [`create-vote-account`](cli/usage.md#solana-create-vote-account) -- [`vote-authorize-voter`](cli/usage.md#solana-vote-authorize-voter) -- [`vote-authorize-voter-checked`](cli/usage.md#solana-vote-authorize-voter-checked) -- [`vote-authorize-withdrawer`](cli/usage.md#solana-vote-authorize-withdrawer) -- [`vote-authorize-withdrawer-checked`](cli/usage.md#solana-vote-authorize-withdrawer-checked) -- [`vote-update-commission`](cli/usage.md#solana-vote-update-commission) -- [`vote-update-validator`](cli/usage.md#solana-vote-update-validator) -- [`withdraw-from-vote-account`](cli/usage.md#solana-withdraw-from-vote-account) +- [`create-vote-account`](../usage.md#solana-create-vote-account) +- [`vote-authorize-voter`](../usage.md#solana-vote-authorize-voter) +- [`vote-authorize-voter-checked`](../usage.md#solana-vote-authorize-voter-checked) +- [`vote-authorize-withdrawer`](../usage.md#solana-vote-authorize-withdrawer) +- [`vote-authorize-withdrawer-checked`](../usage.md#solana-vote-authorize-withdrawer-checked) +- [`vote-update-commission`](../usage.md#solana-vote-update-commission) +- [`vote-update-validator`](../usage.md#solana-vote-update-validator) +- [`withdraw-from-vote-account`](../usage.md#solana-withdraw-from-vote-account) ## Signing Transactions Offline @@ -170,5 +170,5 @@ ohGKvpRC46jAduwU9NW8tP91JkCT5r8Mo67Ysnid4zc76tiiV1Ho6jv3BKFSbBcr2NcPPCarmfTLSkTH Typically a Solana transaction must be signed and accepted by the network within a number of slots from the blockhash in its `recent_blockhash` field (~1min at the time of this writing). If your signing procedure takes longer than this, a -[Durable Transaction Nonce](offline-signing/durable-nonce.md) can give you the extra time you +[Durable Transaction Nonce](./durable-nonce.md) can give you the extra time you need. diff --git a/docs/src/cli/sign-offchain-message.md b/docs/src/cli/examples/sign-offchain-message.md similarity index 98% rename from docs/src/cli/sign-offchain-message.md rename to docs/src/cli/examples/sign-offchain-message.md index 543c5c314a..ae14119f7b 100644 --- a/docs/src/cli/sign-offchain-message.md +++ b/docs/src/cli/examples/sign-offchain-message.md @@ -57,7 +57,7 @@ solana sign-offchain-message -k usb://ledger ``` For more information on how to setup and work with the ledger device see this -[link](../wallet-guide/hardware-wallets/ledger.md). +[link](../wallets/hardware/ledger.md). Please note that UTF-8 encoded messages require `Allow blind sign` option enabled in Solana Ledger App. Also, due to the lack of UTF-8 support in Ledger diff --git a/docs/src/developing/test-validator.md b/docs/src/cli/examples/test-validator.md similarity index 85% rename from docs/src/developing/test-validator.md rename to docs/src/cli/examples/test-validator.md index 5d6c3b0727..70f050c77f 100644 --- a/docs/src/developing/test-validator.md +++ b/docs/src/cli/examples/test-validator.md @@ -1,5 +1,6 @@ --- title: Solana Test Validator +sidebar_label: Test Validator --- During early stage development, it is often convenient to target a cluster with @@ -11,7 +12,7 @@ starts a full-featured, single-node cluster on the developer's workstation. - No RPC rate-limits - No airdrop limits -- Direct [on-chain program](on-chain-programs/overview) deployment +- Direct [on-chain program](https://solana.com/docs/programs) deployment (`--bpf-program ...`) - Clone accounts from a public cluster, including programs (`--clone ...`) - Load accounts from files @@ -22,7 +23,7 @@ starts a full-featured, single-node cluster on the developer's workstation. ## Installation The `solana-test-validator` binary ships with the Solana CLI Tool Suite. -[Install](/cli/install-solana-cli-tools) before continuing. +[Install](../install.md) before continuing. ## Running @@ -125,7 +126,7 @@ Log: test-ledger/validator.log Identity: EPhgPANa5Rh2wa4V2jxt7YbtWa3Uyw4sTeZ13cQjDDB8 ``` -- The validator's identity in the [gossip network](/validator/gossip#gossip-overview) +- The validator's identity in the [gossip network](../../validator/gossip.md#gossip-overview) ``` Version: 1.6.7 @@ -139,8 +140,8 @@ TPU Address: 127.0.0.1:1027 JSON RPC URL: http://127.0.0.1:8899 ``` -- The network address of the [Gossip](/validator/gossip#gossip-overview), - [Transaction Processing Unit](/validator/tpu) and [JSON RPC](../api/http#json-rpc-api-reference) +- The network address of the [Gossip](../../validator/gossip.md#gossip-overview), + [Transaction Processing Unit](../../validator/tpu.md) and [JSON RPC](https://solana.com/docs/rpc) service, respectively ``` @@ -148,15 +149,15 @@ JSON RPC URL: http://127.0.0.1:8899 ``` - Session running time, current slot of the three block - [commitment levels](../api/http#configuring-state-commitment), + [commitment levels](https://solana.com/docs/rpc#configuring-state-commitment), slot height of the last snapshot, transaction count, - [voting authority](/running-validator/vote-accounts#vote-authority) balance + [voting authority](../../operations/guides/vote-accounts.md#vote-authority) balance ## Appendix II: Runtime Features -By default, the test validator runs with all [runtime features](programming-model/runtime#features) activated. +By default, the test validator runs with all [runtime features](https://solana.com/docs/core/runtime#features) activated. -You can verify this using the [Solana command-line tools](cli/install-solana-cli-tools.md): +You can verify this using the [Solana command-line tools](../install.md): ```bash solana feature status -ul diff --git a/docs/src/cli/transfer-tokens.md b/docs/src/cli/examples/transfer-tokens.md similarity index 92% rename from docs/src/cli/transfer-tokens.md rename to docs/src/cli/examples/transfer-tokens.md index 187486ab88..89374ebf43 100644 --- a/docs/src/cli/transfer-tokens.md +++ b/docs/src/cli/examples/transfer-tokens.md @@ -3,12 +3,12 @@ title: Send and Receive Tokens --- This page describes how to receive and send SOL tokens using the command line -tools with a command line wallet such as a [paper wallet](../wallet-guide/paper-wallet.md), -a [file system wallet](../wallet-guide/file-system-wallet.md), or a -[hardware wallet](../wallet-guide/hardware-wallets.md). Before you begin, make sure +tools with a command line wallet such as a [paper wallet](../wallets/paper.md), +a [file system wallet](../wallets/file-system.md), or a +[hardware wallet](../wallets/hardware/index.md). Before you begin, make sure you have created a wallet and have access to its address (pubkey) and the signing keypair. Check out our -[conventions for entering keypairs for different wallet types](../cli/conventions.md#keypair-conventions). +[conventions for entering keypairs for different wallet types](../intro.md#keypair-conventions). ## Testing your Wallet @@ -67,9 +67,9 @@ pubkey: GKvqsuNcnwWqPzzuhLmGi4rzzh55FhJtGizkhHaEJqiV ``` You can also create a second (or more) wallet of any type: -[paper](../wallet-guide/paper-wallet#creating-multiple-paper-wallet-addresses), -[file system](../wallet-guide/file-system-wallet.md#creating-multiple-file-system-wallet-addresses), -or [hardware](../wallet-guide/hardware-wallets.md#multiple-addresses-on-a-single-hardware-wallet). +[paper](../wallets/paper.md#creating-multiple-paper-wallet-addresses), +[file system](../wallets/file-system.md#creating-multiple-file-system-wallet-addresses), +or [hardware](../wallets/hardware/index.md#multiple-addresses-on-a-single-hardware-wallet). #### Transfer tokens from your first wallet to the second address @@ -143,7 +143,7 @@ To receive tokens, you will need an address for others to send tokens to. In Solana, the wallet address is the public key of a keypair. There are a variety of techniques for generating keypairs. The method you choose will depend on how you choose to store keypairs. Keypairs are stored in wallets. Before receiving -tokens, you will need to [create a wallet](../wallet-guide/cli.md). +tokens, you will need to [create a wallet](../wallets/index.md). Once completed, you should have a public key for each keypair you generated. The public key is a long string of base58 characters. Its length varies from 32 to 44 characters. diff --git a/docs/src/cli.md b/docs/src/cli/index.md similarity index 65% rename from docs/src/cli.md rename to docs/src/cli/index.md index a4461c6d76..cdf1ed10f8 100644 --- a/docs/src/cli.md +++ b/docs/src/cli/index.md @@ -1,10 +1,12 @@ --- -title: Command-line Guide +title: Solana CLI Tool Suite +sidebar_label: Overview +sidebar_position: 0 --- In this section, we will describe how to use the Solana command-line tools to -create a _wallet_, to send and receive SOL tokens, and to participate in -the cluster by delegating stake. +create a _wallet_, to send and receive SOL tokens, and to participate in the +cluster by delegating stake. To interact with a Solana cluster, we will use its command-line interface, also known as the CLI. We use the command-line because it is the first place the @@ -16,7 +18,7 @@ secure access to your Solana accounts. To get started using the Solana Command Line (CLI) tools: -- [Install the Solana Tools](cli/install-solana-cli-tools.md) -- [Choose a Cluster](cli/choose-a-cluster.md) -- [Create a Wallet](wallet-guide/cli.md) -- [Check out our CLI conventions](cli/conventions.md) +- [Install the Solana CLI Tool Suite](./install.md) +- [Choose a Cluster](./examples/choose-a-cluster.md) +- [Create a Wallet](./wallets/index.md) +- [Introduction to our CLI conventions](./intro.md) diff --git a/docs/src/cli/install-solana-cli-tools.md b/docs/src/cli/install.md similarity index 98% rename from docs/src/cli/install-solana-cli-tools.md rename to docs/src/cli/install.md index 26a4ede5af..06efc82851 100644 --- a/docs/src/cli/install-solana-cli-tools.md +++ b/docs/src/cli/install.md @@ -1,5 +1,7 @@ --- -title: Install the Solana Tool Suite +title: Install the Solana CLI +sidebar_label: Installation +sidebar_position: 1 --- There are multiple ways to install the Solana tools on your computer diff --git a/docs/src/cli/conventions.md b/docs/src/cli/intro.md similarity index 91% rename from docs/src/cli/conventions.md rename to docs/src/cli/intro.md index 7f97132ba5..1701450173 100644 --- a/docs/src/cli/conventions.md +++ b/docs/src/cli/intro.md @@ -1,5 +1,7 @@ --- -title: Using Solana CLI +title: Introduction to the Solana CLI +sidebar_label: Introduction +sidebar_position: 2 --- Before running any Solana CLI commands, let's go over some conventions that @@ -31,7 +33,7 @@ the base58 encoding of your public key, such as Many commands using the CLI tools require a value for a ``. The value you should use for the keypair depends on what type of -[command line wallet you created](../wallet-guide/cli.md). +[command line wallet you created](./wallets/index.md). For example, the CLI help shows that the way to display any wallet's address (also known as the keypair's pubkey), is: @@ -72,7 +74,7 @@ solana-keygen pubkey /home/solana/my_wallet.json #### Hardware Wallet If you chose a hardware wallet, use your -[keypair URL](../wallet-guide/hardware-wallets.md#specify-a-hardware-wallet-key), +[keypair URL](./wallets/hardware/index.md#specify-a-hardware-wallet-key), such as `usb://ledger?key=0`. ```bash diff --git a/docs/src/cli/wallets/_category_.json b/docs/src/cli/wallets/_category_.json new file mode 100644 index 0000000000..e420a33bb4 --- /dev/null +++ b/docs/src/cli/wallets/_category_.json @@ -0,0 +1,7 @@ +{ + "position": 3.5, + "label": "Command-line Wallets", + "collapsible": true, + "collapsed": false, + "link": null +} diff --git a/docs/src/wallet-guide/file-system-wallet.md b/docs/src/cli/wallets/file-system.md similarity index 95% rename from docs/src/wallet-guide/file-system-wallet.md rename to docs/src/cli/wallets/file-system.md index 90fb5c2926..0041c51876 100644 --- a/docs/src/wallet-guide/file-system-wallet.md +++ b/docs/src/cli/wallets/file-system.md @@ -1,5 +1,6 @@ --- -title: File System Wallet +title: File System Wallets +sidebar_position: 2 --- This document describes how to create and use a file system wallet with the @@ -11,7 +12,7 @@ on your computer system's filesystem. ## Before you Begin Make sure you have -[installed the Solana Command Line Tools](../cli/install-solana-cli-tools.md) +[installed the Solana Command Line Tools](../install.md) ## Generate a File System Wallet Keypair diff --git a/docs/src/cli/wallets/hardware/_category_.json b/docs/src/cli/wallets/hardware/_category_.json new file mode 100644 index 0000000000..d000fb2312 --- /dev/null +++ b/docs/src/cli/wallets/hardware/_category_.json @@ -0,0 +1,7 @@ +{ + "position": 5, + "label": "Hardware Wallets", + "collapsible": false, + "collapsed": false, + "link": null +} diff --git a/docs/src/wallet-guide/hardware-wallets.md b/docs/src/cli/wallets/hardware/index.md similarity index 92% rename from docs/src/wallet-guide/hardware-wallets.md rename to docs/src/cli/wallets/hardware/index.md index 01d98b0318..9c8642cf34 100644 --- a/docs/src/wallet-guide/hardware-wallets.md +++ b/docs/src/cli/wallets/hardware/index.md @@ -1,5 +1,7 @@ --- -title: Using Hardware Wallets on the Solana CLI +title: Using Hardware Wallets in the Solana CLI +sidebar_label: Using in the Solana CLI +sidebar_position: 0 --- Signing a transaction requires a private key, but storing a private @@ -19,7 +21,7 @@ hardware wallet. The Solana CLI supports the following hardware wallets: -- [Ledger Nano S and Ledger Nano X](hardware-wallets/ledger.md) +- [Ledger Nano S and Ledger Nano X](./ledger.md) ## Specify a Keypair URL diff --git a/docs/src/wallet-guide/hardware-wallets/ledger.md b/docs/src/cli/wallets/hardware/ledger.md similarity index 61% rename from docs/src/wallet-guide/hardware-wallets/ledger.md rename to docs/src/cli/wallets/hardware/ledger.md index bb3f0ebfbe..65935b79d0 100644 --- a/docs/src/wallet-guide/hardware-wallets/ledger.md +++ b/docs/src/cli/wallets/hardware/ledger.md @@ -1,14 +1,15 @@ --- -title: Ledger Nano +title: Using Ledger Nano Hardware Wallets in the Solana CLI +sidebar_label: Ledger Nano --- -This page describes how to use a Ledger Nano S, Nano S Plus, or Nano X to interact with Solana -using the command line tools. +This page describes how to use a Ledger Nano S, Nano S Plus, or Nano X to +interact with Solana using the command line tools. ## Before You Begin - [Set up a Nano with the Solana App](https://support.ledger.com/hc/en-us/articles/360016265659-Solana-SOL-?docs=true) -- [Install the Solana command-line tools](../../cli/install-solana-cli-tools.md) +- [Install the Solana command-line tools](../../install.md) ## Use Ledger Nano with Solana CLI @@ -27,18 +28,18 @@ solana-keygen pubkey usb://ledger This confirms your Ledger device is connected properly and in the correct state to interact with the Solana CLI. The command returns your Ledger's unique -_wallet ID_. When you have multiple Nano devices connected to the same -computer, you can use your wallet ID to specify which Ledger hardware wallet -you want to use. If you only plan to use a single Nano on your computer -at a time, you don't need to include the wallet ID. For information on -using the wallet ID to use a specific Ledger, see +_wallet ID_. When you have multiple Nano devices connected to the same computer, +you can use your wallet ID to specify which Ledger hardware wallet you want to +use. If you only plan to use a single Nano on your computer at a time, you don't +need to include the wallet ID. For information on using the wallet ID to use a +specific Ledger, see [Manage Multiple Hardware Wallets](#manage-multiple-hardware-wallets). ### View your Wallet Addresses -Your Nano supports an arbitrary number of valid wallet addresses and signers. -To view any address, use the `solana-keygen pubkey` command, as shown below, -followed by a valid [keypair URL](../hardware-wallets.md#specify-a-keypair-url). +Your Nano supports an arbitrary number of valid wallet addresses and signers. To +view any address, use the `solana-keygen pubkey` command, as shown below, +followed by a valid [keypair URL](./index.md#specify-a-keypair-url). Multiple wallet addresses can be useful if you want to transfer tokens between your own accounts for different purposes, or use different keypairs on the @@ -57,12 +58,11 @@ solana-keygen pubkey usb://ledger?key=2 - NOTE: keypair url parameters are ignored in **zsh**  [see troubleshooting for more info](#troubleshooting) -You can use other values for the number after `key=` as well. -Any of the addresses displayed by these commands are valid Solana wallet -addresses. The private portion associated with each address is stored securely -on the Nano, and is used to sign transactions from this address. -Just make a note of which keypair URL you used to derive any address you will be -using to receive tokens. +You can use other values for the number after `key=` as well. Any of the +addresses displayed by these commands are valid Solana wallet addresses. The +private portion associated with each address is stored securely on the Nano, and +is used to sign transactions from this address. Just make a note of which +keypair URL you used to derive any address you will be using to receive tokens. If you are only planning to use a single address/keypair on your device, a good easy-to-remember path might be to use the address at `key=0`. View this address @@ -93,26 +93,26 @@ solana balance 7cvkjYAkUYs4W8XcXsca7cBrEGFeSUjeZmKoNBvEwyri ``` You can also view the balance of any account address on the Accounts tab in the -[Explorer](https://explorer.solana.com/accounts) -and paste the address in the box to view the balance in you web browser. +[Explorer](https://explorer.solana.com/accounts) and paste the address in the +box to view the balance in you web browser. Note: Any address with a balance of 0 SOL, such as a newly created one on your -Ledger, will show as "Not Found" in the explorer. Empty accounts and non-existent -accounts are treated the same in Solana. This will change when your account -address has some SOL in it. +Ledger, will show as "Not Found" in the explorer. Empty accounts and +non-existent accounts are treated the same in Solana. This will change when your +account address has some SOL in it. ### Send SOL from a Nano -To send some tokens from an address controlled by your Nano, you will -need to use the device to sign a transaction, using the same keypair URL you -used to derive the address. To do this, make sure your Nano is plugged in, -unlocked with the PIN, Ledger Live is not running, and the Solana App is open -on the device, showing "Application is Ready". +To send some tokens from an address controlled by your Nano, you will need to +use the device to sign a transaction, using the same keypair URL you used to +derive the address. To do this, make sure your Nano is plugged in, unlocked with +the PIN, Ledger Live is not running, and the Solana App is open on the device, +showing "Application is Ready". -The `solana transfer` command is used to specify to which address to send tokens, -how many tokens to send, and uses the `--keypair` argument to specify which -keypair is sending the tokens, which will sign the transaction, and the balance -from the associated address will decrease. +The `solana transfer` command is used to specify to which address to send +tokens, how many tokens to send, and uses the `--keypair` argument to specify +which keypair is sending the tokens, which will sign the transaction, and the +balance from the associated address will decrease. ```bash solana transfer RECIPIENT_ADDRESS AMOUNT --keypair KEYPAIR_URL_OF_SENDER @@ -120,12 +120,12 @@ solana transfer RECIPIENT_ADDRESS AMOUNT --keypair KEYPAIR_URL_OF_SENDER Below is a full example. First, an address is viewed at a certain keypair URL. Second, the balance of that address is checked. Lastly, a transfer transaction -is entered to send `1` SOL to the recipient address `7cvkjYAkUYs4W8XcXsca7cBrEGFeSUjeZmKoNBvEwyri`. -When you hit Enter for a transfer command, you will be prompted to approve the -transaction details on your Ledger device. On the device, use the right and -left buttons to review the transaction details. If they look correct, click -both buttons on the "Approve" screen, otherwise push both buttons on the "Reject" -screen. +is entered to send `1` SOL to the recipient address +`7cvkjYAkUYs4W8XcXsca7cBrEGFeSUjeZmKoNBvEwyri`. When you hit Enter for a +transfer command, you will be prompted to approve the transaction details on +your Ledger device. On the device, use the right and left buttons to review the +transaction details. If they look correct, click both buttons on the "Approve" +screen, otherwise push both buttons on the "Reject" screen. ```bash ~$ solana-keygen pubkey usb://ledger?key=42 @@ -146,8 +146,8 @@ transaction signature, and wait for the maximum number of confirmations (32) before returning. This only takes a few seconds, and then the transaction is finalized on the Solana network. You can view details of this or any other transaction by going to the Transaction tab in the -[Explorer](https://explorer.solana.com/transactions) -and paste in the transaction signature. +[Explorer](https://explorer.solana.com/transactions) and paste in the +transaction signature. ## Advanced Operations @@ -155,14 +155,13 @@ and paste in the transaction signature. It is sometimes useful to sign a transaction with keys from multiple hardware wallets. Signing with multiple wallets requires _fully qualified keypair URLs_. -When the URL is not fully qualified, the Solana CLI will prompt you with -the fully qualified URLs of all connected hardware wallets, and ask you to -choose which wallet to use for each signature. +When the URL is not fully qualified, the Solana CLI will prompt you with the +fully qualified URLs of all connected hardware wallets, and ask you to choose +which wallet to use for each signature. -Instead of using the interactive prompts, you can generate fully qualified -URLs using the Solana CLI `resolve-signer` command. For example, try -connecting a Nano to USB, unlock it with your pin, and running the -following command: +Instead of using the interactive prompts, you can generate fully qualified URLs +using the Solana CLI `resolve-signer` command. For example, try connecting a +Nano to USB, unlock it with your pin, and running the following command: ```text solana resolve-signer usb://ledger?key=0/0 @@ -176,11 +175,11 @@ usb://ledger/BsNsvfXqQTtJnagwFWdBS7FBXgnsK8VZ5CmuznN85swK?key=0/0 but where `BsNsvfXqQTtJnagwFWdBS7FBXgnsK8VZ5CmuznN85swK` is your `WALLET_ID`. -With your fully qualified URL, you can connect multiple hardware wallets to -the same computer and uniquely identify a keypair from any of them. -Use the output from the `resolve-signer` command anywhere a `solana` command -expects a `` entry to use that resolved path as the signer for that -part of the given transaction. +With your fully qualified URL, you can connect multiple hardware wallets to the +same computer and uniquely identify a keypair from any of them. Use the output +from the `resolve-signer` command anywhere a `solana` command expects a +`` entry to use that resolved path as the signer for that part of the +given transaction. ## Troubleshooting @@ -210,9 +209,9 @@ solana-keygen pubkey usb://ledger\?key=0 ## Support -Check out our [Wallet Support Page](../support.md) -for ways to get help. +You can find additional support and get help on the +[Solana StackExchange](https://solana.stackexchange.com). -Read more about [sending and receiving tokens](../../cli/transfer-tokens.md) and -[delegating stake](../../cli/delegate-stake.md). You can use your Ledger keypair URL -anywhere you see an option or argument that accepts a ``. +Read more about [sending and receiving tokens](../../examples/transfer-tokens.md) and +[delegating stake](../../examples/delegate-stake.md). You can use your Ledger keypair +URL anywhere you see an option or argument that accepts a ``. diff --git a/docs/src/wallet-guide/cli.md b/docs/src/cli/wallets/index.md similarity index 86% rename from docs/src/wallet-guide/cli.md rename to docs/src/cli/wallets/index.md index 841dc7264d..fcd907629c 100644 --- a/docs/src/wallet-guide/cli.md +++ b/docs/src/cli/wallets/index.md @@ -1,11 +1,13 @@ --- title: Command Line Wallets +sidebar_label: Overview +sidebar_position: 0 --- Solana supports several different types of wallets that can be used to interface directly with the Solana command-line tools. -To use a Command Line Wallet, you must first [install the Solana CLI tools](../cli/install-solana-cli-tools.md) +To use a Command Line Wallet, you must first [install the Solana CLI tools](../install.md) ## File System Wallet @@ -26,7 +28,7 @@ keypairs are stored on your computer as files, a skilled hacker with physical access to your computer may be able to access it. Using an encrypted hard drive, such as FileVault on MacOS, minimizes that risk. -[File System Wallet](file-system-wallet.md) +See [File System Wallets](./file-system.md) for more details. ## Paper Wallet @@ -39,9 +41,9 @@ regenerate a keypair on demand. In terms of convenience versus security, a paper wallet sits at the opposite side of the spectrum from an FS wallet. It is terribly inconvenient to use, but offers excellent security. That high security is further amplified when paper -wallets are used in conjunction with [offline signing](../offline-signing.md). +wallets are used in conjunction with [offline signing](../examples/offline-signing.md). -[Paper Wallets](paper-wallet.md) +See [Paper Wallets](./paper.md) for more details ## Hardware Wallet @@ -56,4 +58,4 @@ security and convenience for cryptocurrencies. It effectively automates the process of offline signing while retaining nearly all the convenience of a file system wallet. -[Hardware Wallets](hardware-wallets.md) +See [Hardware Wallets](./hardware/index.md) for more details diff --git a/docs/src/wallet-guide/paper-wallet.md b/docs/src/cli/wallets/paper.md similarity index 82% rename from docs/src/wallet-guide/paper-wallet.md rename to docs/src/cli/wallets/paper.md index bb6336507c..85c76779b8 100644 --- a/docs/src/wallet-guide/paper-wallet.md +++ b/docs/src/cli/wallets/paper.md @@ -1,11 +1,13 @@ --- -title: Paper Wallet +title: Paper Wallets +sidebar_position: 1 --- This document describes how to create and use a paper wallet with the Solana CLI tools. -> We do not intend to advise on how to _securely_ create or manage paper wallets. Please research the security concerns carefully. +> We do not intend to advise on how to _securely_ create or manage paper +> wallets. Please research the security concerns carefully. ## Overview @@ -20,11 +22,13 @@ Solana commands can be run without ever saving a keypair to disk on a machine. If avoiding writing a private key to disk is a security concern of yours, you've come to the right place. -> Even using this secure input method, it's still possible that a private key gets written to disk by unencrypted memory swaps. It is the user's responsibility to protect against this scenario. +> Even using this secure input method, it's still possible that a private key +> gets written to disk by unencrypted memory swaps. It is the user's +> responsibility to protect against this scenario. ## Before You Begin -- [Install the Solana command-line tools](../cli/install-solana-cli-tools.md) +- [Install the Solana command-line tools](../install.md) ### Check your installation @@ -42,7 +46,8 @@ The seed phrase and passphrase can be used together as a paper wallet. As long as you keep your seed phrase and passphrase stored safely, you can use them to access your account. -> For more information about how seed phrases work, review this [Bitcoin Wiki page](https://en.bitcoin.it/wiki/Seed_phrase). +> For more information about how seed phrases work, review this +> [Bitcoin Wiki page](https://en.bitcoin.it/wiki/Seed_phrase). ### Seed Phrase Generation @@ -59,7 +64,9 @@ have not made any errors. solana-keygen new --no-outfile ``` -> If the `--no-outfile` flag is **omitted**, the default behavior is to write the keypair to `~/.config/solana/id.json`, resulting in a [file system wallet](file-system-wallet.md). +> If the `--no-outfile` flag is **omitted**, the default behavior is to write +> the keypair to `~/.config/solana/id.json`, resulting in a +> [file system wallet](./file-system.md). The output of this command will display a line like this: @@ -69,10 +76,11 @@ pubkey: 9ZNTfG4NyQgxy2SWjSiQoUyBPEvXT2xo7fKc5hPYYJ7b The value shown after `pubkey:` is your _wallet address_. -**Note:** In working with paper wallets and file system wallets, the terms "pubkey" -and "wallet address" are sometimes used interchangeably. +**Note:** In working with paper wallets and file system wallets, the terms +"pubkey" and "wallet address" are sometimes used interchangeably. -> For added security, increase the seed phrase word count using the `--word-count` argument +> For added security, increase the seed phrase word count using the +> `--word-count` argument For full usage details, run: @@ -80,7 +88,6 @@ For full usage details, run: solana-keygen new --help ``` - ### Public Key Derivation Public keys can be derived from a seed phrase and a passphrase if you choose to @@ -93,7 +100,8 @@ with the solana command-line tools using the `prompt` URI scheme. solana-keygen pubkey prompt:// ``` -> Note that you could potentially use different passphrases for the same seed phrase. Each unique passphrase will yield a different keypair. +> Note that you could potentially use different passphrases for the same seed +> phrase. Each unique passphrase will yield a different keypair. The `solana-keygen` tool uses the same BIP39 standard English word list as it does to generate seed phrases. If your seed phrase was generated with another @@ -105,19 +113,22 @@ validation. solana-keygen pubkey prompt:// --skip-seed-phrase-validation ``` -After entering your seed phrase with `solana-keygen pubkey prompt://` the console -will display a string of base-58 characters. This is the [derived](#hierarchical-derivation) solana BIP44 _wallet address_ -associated with your seed phrase. +After entering your seed phrase with `solana-keygen pubkey prompt://` the +console will display a string of base-58 characters. This is the +[derived](#hierarchical-derivation) solana BIP44 _wallet address_ associated +with your seed phrase. > Copy the derived address to a USB stick for easy usage on networked computers -If needed, you can access the legacy, raw keypair's pubkey by instead passing the `ASK` keyword: +If needed, you can access the legacy, raw keypair's pubkey by instead passing +the `ASK` keyword: ```bash solana-keygen pubkey ASK ``` -> A common next step is to [check the balance](#checking-account-balance) of the account associated with a public key +> A common next step is to [check the balance](#checking-account-balance) of the +> account associated with a public key For full usage details, run: @@ -140,7 +151,8 @@ derive a child key, supply the `?key=/` query string. solana-keygen pubkey prompt://?key=0/1 ``` -To use a derivation path other than solana's standard BIP44, you can supply `?full-path=m////`. +To use a derivation path other than solana's standard BIP44, you can supply +`?full-path=m////`. ```bash solana-keygen pubkey prompt://?full-path=m/44/2017/0/1 @@ -178,7 +190,7 @@ Public keys can then be typed manually or transferred via a USB stick to a networked machine. Next, configure the `solana` CLI tool to -[connect to a particular cluster](../cli/choose-a-cluster.md): +[connect to a particular cluster](../examples/choose-a-cluster.md): ```bash solana config set --url # (i.e. https://api.mainnet-beta.solana.com) @@ -192,12 +204,13 @@ solana balance ## Creating Multiple Paper Wallet Addresses -You can create as many wallet addresses as you like. Simply re-run the -steps in [Seed Phrase Generation](#seed-phrase-generation) or +You can create as many wallet addresses as you like. Simply re-run the steps in +[Seed Phrase Generation](#seed-phrase-generation) or [Public Key Derivation](#public-key-derivation) to create a new address. Multiple wallet addresses can be useful if you want to transfer tokens between your own accounts for different purposes. ## Support -Check out our [Wallet Support Page](support.md) for ways to get help. +You can find additional support and get help on the +[Solana StackExchange](https://solana.stackexchange.com). diff --git a/docs/src/cluster/fork-generation.md b/docs/src/cluster/fork-generation.md deleted file mode 100644 index 2ab6e1d70c..0000000000 --- a/docs/src/cluster/fork-generation.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Fork Generation -description: "A fork is created when validators do not agree on a newly produced block. Using a consensus algorithm validators vote on which will be finalized." ---- - -The Solana protocol doesn’t wait for all validators to agree on a newly produced block before the next block is produced. Because of that, it’s quite common for two different blocks to be chained to the same parent block. In those situations, we call each conflicting chain a [“fork.”](./fork-generation.md) - -Solana validators need to vote on one of these forks and reach agreement on which one to use through a consensus algorithm (that is beyond the scope of this article). The main point you need to remember is that when there are competing forks, only one fork will be finalized by the cluster and the abandoned blocks in competing forks are all discarded. - -This section describes how forks naturally occur as a consequence of [leader rotation](./leader-rotation.md). - -## Overview - -Nodes take turns being [leader](./../terminology.md#leader) and generating the PoH that encodes state changes. The cluster can tolerate loss of connection to any leader by synthesizing what the leader _**would**_ have generated had it been connected but not ingesting any state changes. - -The possible number of forks is thereby limited to a "there/not-there" skip list of forks that may arise on leader rotation slot boundaries. At any given slot, only a single leader's transactions will be accepted. - -### Forking example - -The table below illustrates what competing forks could look like. Time progresses from left to right and each slot is assigned to a validator that temporarily becomes the cluster “leader” and may produce a block for that slot. - -In this example, the leader for slot 3 chose to chain its “Block 3” directly to “Block 1” and in doing so skipped “Block 2”. Similarly, the leader for slot 5 chose to chain “Block 5” directly to “Block 3” and skipped “Block 4”. - -> Note that across different forks, the block produced for a given slot is _always_ the same because producing two different blocks for the same slot is a slashable offense. So the conflicting forks above can be distinguished from each other by which slots they have _skipped_. - -| | Slot 1 | Slot 2 | Slot 3 | Slot 4 | Slot 5 | -| ------ | ------- | ------- | ------- | ------- | ------- | -| Fork 1 | Block 1 | | Block 3 | | Block 5 | -| Fork 2 | Block 1 | | Block 3 | Block 4 | | -| Fork 3 | Block 1 | Block 2 | | | | - -## Message Flow - -1. Transactions are ingested by the current leader. -2. Leader filters valid transactions. -3. Leader executes valid transactions updating its state. -4. Leader packages transactions into entries based off its current PoH slot. -5. Leader transmits the entries to validator nodes \(in signed shreds\) - 1. The PoH stream includes ticks; empty entries that indicate liveness of the leader and the passage of time on the cluster. - 2. A leader's stream begins with the tick entries necessary to complete PoH back to the leader's most recently observed prior leader slot. -6. Validators retransmit entries to peers in their set and to further downstream nodes. -7. Validators validate the transactions and execute them on their state. -8. Validators compute the hash of the state. -9. At specific times, i.e. specific PoH tick counts, validators transmit votes to the leader. - 1. Votes are signatures of the hash of the computed state at that PoH tick count. - 2. Votes are also propagated via gossip. -10. Leader executes the votes, the same as any other transaction, and broadcasts them to the cluster. -11. Validators observe their votes and all the votes from the cluster. - -## Partitions, Forks - -Forks can arise at PoH tick counts that correspond to a vote. The next leader may not have observed the last vote slot and may start their slot with generated virtual PoH entries. These empty ticks are generated by all nodes in the cluster at a cluster-configured rate for hashes/per/tick `Z`. - -There are only two possible versions of the PoH during a voting slot: PoH with `T` ticks and entries generated by the current leader, or PoH with just ticks. The "just ticks" version of the PoH can be thought of as a virtual ledger, one that all nodes in the cluster can derive from the last tick in the previous slot. - -Validators can ignore forks at other points \(e.g. from the wrong leader\), or slash the leader responsible for the fork. - -Validators vote based on a greedy choice to maximize their reward described in [Tower BFT](../implemented-proposals/tower-bft.md). - -### Validator's View - -#### Time Progression - -The diagram below represents a validator's view of the PoH stream with possible forks over time. L1, L2, etc. are leader slots, and `E`s represent entries from that leader during that leader's slot. The `x`s represent ticks only, and time flows downwards in the diagram. - -![Fork generation](/img/fork-generation.svg) - -Note that an `E` appearing on 2 forks at the same slot is a slashable condition, so a validator observing `E3` and `E3'` can slash L3 and safely choose `x` for that slot. Once a validator commits to a fork, other forks can be discarded below that tick count. For any slot, validators need only consider a single "has entries" chain or a "ticks only" chain to be proposed by a leader. But multiple virtual entries may overlap as they link back to the a previous slot. - -#### Time Division - -It's useful to consider leader rotation over PoH tick count as time division of the job of encoding state for the cluster. The following table presents the above tree of forks as a time-divided ledger. - -| leader slot | L1 | L2 | L3 | L4 | L5 | -| :--------------- | :-- | :-- | :-- | :-- | :-- | -| data | E1 | E2 | E3 | E4 | E5 | -| ticks since prev | | | | x | xx | - -Note that only data from leader L3 will be accepted during leader slot L3. Data from L3 may include "catchup" ticks back to a slot other than L2 if L3 did not observe L2's data. L4 and L5's transmissions include the "ticks to prev" PoH entries. - -This arrangement of the network data streams permits nodes to save exactly this to the ledger for replay, restart, and checkpoints. - -### Leader's View - -When a new leader begins a slot, it must first transmit any PoH \(ticks\) required to link the new slot with the most recently observed and voted slot. The fork the leader proposes would link the current slot to a previous fork that the leader has voted on with virtual ticks. diff --git a/docs/src/cluster/rpc-endpoints.md b/docs/src/cluster/rpc-endpoints.md deleted file mode 100644 index 50173fa908..0000000000 --- a/docs/src/cluster/rpc-endpoints.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Solana Cluster RPC Endpoints ---- - -Solana maintains dedicated api nodes to fulfill [JSON-RPC](/api) -requests for each public cluster, and third parties may as well. Here are the -public RPC endpoints currently available and recommended for each public cluster: - -## Devnet - -#### Endpoint - -- `https://api.devnet.solana.com` - single Solana-hosted api node; rate-limited - -#### Rate Limits - -- Maximum number of requests per 10 seconds per IP: 100 -- Maximum number of requests per 10 seconds per IP for a single RPC: 40 -- Maximum concurrent connections per IP: 40 -- Maximum connection rate per 10 seconds per IP: 40 -- Maximum amount of data per 30 second: 100 MB - -## Testnet - -#### Endpoint - -- `https://api.testnet.solana.com` - single Solana-hosted api node; rate-limited - -#### Rate Limits - -- Maximum number of requests per 10 seconds per IP: 100 -- Maximum number of requests per 10 seconds per IP for a single RPC: 40 -- Maximum concurrent connections per IP: 40 -- Maximum connection rate per 10 seconds per IP: 40 -- Maximum amount of data per 30 second: 100 MB - -## Mainnet Beta - -#### Endpoints\* - -- `https://api.mainnet-beta.solana.com` - Solana-hosted api node cluster, backed by a load balancer; rate-limited - -#### Rate Limits - -- Maximum number of requests per 10 seconds per IP: 100 -- Maximum number of requests per 10 seconds per IP for a single RPC: 40 -- Maximum concurrent connections per IP: 40 -- Maximum connection rate per 10 seconds per IP: 40 -- Maximum amount of data per 30 second: 100 MB - -\*The public RPC endpoints are not intended for production applications. Please -use dedicated/private RPC servers when you launch your application, drop NFTs, -etc. The public services are subject to abuse and rate limits may change -without prior notice. Likewise, high-traffic websites may be blocked without -prior notice. - -## Common HTTP Error Codes - -- 403 -- Your IP address or website has been blocked. It is time to run your own RPC server(s) or find a private service. -- 429 -- Your IP address is exceeding the rate limits. Slow down! Use the - [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) - HTTP response header to determine how long to wait before making another - request. diff --git a/docs/src/cluster/stake-delegation-and-rewards.md b/docs/src/cluster/stake-delegation-and-rewards.md deleted file mode 100644 index e147e0db3f..0000000000 --- a/docs/src/cluster/stake-delegation-and-rewards.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: Stake Delegation and Rewards ---- - -Stakers are rewarded for helping to validate the ledger. They do this by delegating their stake to validator nodes. Those validators do the legwork of replaying the ledger and sending votes to a per-node vote account to which stakers can delegate their stakes. The rest of the cluster uses those stake-weighted votes to select a block when forks arise. Both the validator and staker need some economic incentive to play their part. The validator needs to be compensated for its hardware and the staker needs to be compensated for the risk of getting its stake slashed. The economics are covered in [staking rewards](../implemented-proposals/staking-rewards.md). This section, on the other hand, describes the underlying mechanics of its implementation. - -## Basic Design - -The general idea is that the validator owns a Vote account. The Vote account tracks validator votes, counts validator generated credits, and provides any additional validator specific state. The Vote account is not aware of any stakes delegated to it and has no staking weight. - -A separate Stake account \(created by a staker\) names a Vote account to which the stake is delegated. Rewards generated are proportional to the amount of lamports staked. The Stake account is owned by the staker only. Some portion of the lamports stored in this account are the stake. - -## Passive Delegation - -Any number of Stake accounts can delegate to a single Vote account without an interactive action from the identity controlling the Vote account or submitting votes to the account. - -The total stake allocated to a Vote account can be calculated by the sum of all the Stake accounts that have the Vote account pubkey as the `StakeStateV2::Stake::voter_pubkey`. - -## Vote and Stake accounts - -The rewards process is split into two on-chain programs. The Vote program solves the problem of making stakes slashable. The Stake program acts as custodian of the rewards pool and provides for passive delegation. The Stake program is responsible for paying rewards to staker and voter when shown that a staker's delegate has participated in validating the ledger. - -### VoteState - -VoteState is the current state of all the votes the validator has submitted to the network. VoteState contains the following state information: - -- `votes` - The submitted votes data structure. -- `credits` - The total number of rewards this Vote program has generated over its lifetime. -- `root_slot` - The last slot to reach the full lockout commitment necessary for rewards. -- `commission` - The commission taken by this VoteState for any rewards claimed by staker's Stake accounts. This is the percentage ceiling of the reward. -- Account::lamports - The accumulated lamports from the commission. These do not count as stakes. -- `authorized_voter` - Only this identity is authorized to submit votes. This field can only modified by this identity. -- `node_pubkey` - The Solana node that votes in this account. -- `authorized_withdrawer` - the identity of the entity in charge of the lamports of this account, separate from the account's address and the authorized vote signer. - -### VoteInstruction::Initialize\(VoteInit\) - -- `account[0]` - RW - The VoteState. - - `VoteInit` carries the new vote account's `node_pubkey`, `authorized_voter`, `authorized_withdrawer`, and `commission`. - - other VoteState members defaulted. - -### VoteInstruction::Authorize\(Pubkey, VoteAuthorize\) - -Updates the account with a new authorized voter or withdrawer, according to the VoteAuthorize parameter \(`Voter` or `Withdrawer`\). The transaction must be signed by the Vote account's current `authorized_voter` or `authorized_withdrawer`. - -- `account[0]` - RW - The VoteState. - `VoteState::authorized_voter` or `authorized_withdrawer` is set to `Pubkey`. - -### VoteInstruction::AuthorizeWithSeed\(VoteAuthorizeWithSeedArgs\) - -Updates the account with a new authorized voter or withdrawer, according to the VoteAuthorize parameter \(`Voter` or `Withdrawer`\). Unlike `VoteInstruction::Authorize` this instruction is for use when the Vote account's current `authorized_voter` or `authorized_withdrawer` is a derived key. The transaction must be signed by someone who can sign for the base key of that derived key. - -- `account[0]` - RW - The VoteState. - `VoteState::authorized_voter` or `authorized_withdrawer` is set to `Pubkey`. - -### VoteInstruction::Vote\(Vote\) - -- `account[0]` - RW - The VoteState. - `VoteState::lockouts` and `VoteState::credits` are updated according to voting lockout rules see [Tower BFT](../implemented-proposals/tower-bft.md). -- `account[1]` - RO - `sysvar::slot_hashes` A list of some N most recent slots and their hashes for the vote to be verified against. -- `account[2]` - RO - `sysvar::clock` The current network time, expressed in slots, epochs. - -### StakeStateV2 - -A StakeStateV2 takes one of four forms, StakeStateV2::Uninitialized, StakeStateV2::Initialized, StakeStateV2::Stake, and StakeStateV2::RewardsPool. Only the first three forms are used in staking, but only StakeStateV2::Stake is interesting. All RewardsPools are created at genesis. - -### StakeStateV2::Stake - -StakeStateV2::Stake is the current delegation preference of the **staker** and contains the following state information: - -- Account::lamports - The lamports available for staking. -- `stake` - the staked amount \(subject to warmup and cooldown\) for generating rewards, always less than or equal to Account::lamports. -- `voter_pubkey` - The pubkey of the VoteState instance the lamports are delegated to. -- `credits_observed` - The total credits claimed over the lifetime of the program. -- `activated` - the epoch at which this stake was activated/delegated. The full stake will be counted after warmup. -- `deactivated` - the epoch at which this stake was de-activated, some cooldown epochs are required before the account is fully deactivated, and the stake available for withdrawal. -- `authorized_staker` - the pubkey of the entity that must sign delegation, activation, and deactivation transactions. -- `authorized_withdrawer` - the identity of the entity in charge of the lamports of this account, separate from the account's address, and the authorized staker. - -### StakeStateV2::RewardsPool - -To avoid a single network-wide lock or contention in redemption, 256 RewardsPools are part of genesis under pre-determined keys, each with std::u64::MAX credits to be able to satisfy redemptions according to point value. - -The Stakes and the RewardsPool are accounts that are owned by the same `Stake` program. - -### StakeInstruction::DelegateStake - -The Stake account is moved from Initialized to StakeStateV2::Stake form, or from a deactivated (i.e. fully cooled-down) StakeStateV2::Stake to activated StakeStateV2::Stake. This is how stakers choose the vote account and validator node to which their stake account lamports are delegated. The transaction must be signed by the stake's `authorized_staker`. - -- `account[0]` - RW - The StakeStateV2::Stake instance. `StakeStateV2::Stake::credits_observed` is initialized to `VoteState::credits`, `StakeStateV2::Stake::voter_pubkey` is initialized to `account[1]`. If this is the initial delegation of stake, `StakeStateV2::Stake::stake` is initialized to the account's balance in lamports, `StakeStateV2::Stake::activated` is initialized to the current Bank epoch, and `StakeStateV2::Stake::deactivated` is initialized to std::u64::MAX -- `account[1]` - R - The VoteState instance. -- `account[2]` - R - sysvar::clock account, carries information about current Bank epoch. -- `account[3]` - R - sysvar::stakehistory account, carries information about stake history. -- `account[4]` - R - stake::Config account, carries warmup, cooldown, and slashing configuration. - -### StakeInstruction::Authorize\(Pubkey, StakeAuthorize\) - -Updates the account with a new authorized staker or withdrawer, according to the StakeAuthorize parameter \(`Staker` or `Withdrawer`\). The transaction must be by signed by the Stakee account's current `authorized_staker` or `authorized_withdrawer`. Any stake lock-up must have expired, or the lock-up custodian must also sign the transaction. - -- `account[0]` - RW - The StakeStateV2. - - `StakeStateV2::authorized_staker` or `authorized_withdrawer` is set to to `Pubkey`. - -### StakeInstruction::Deactivate - -A staker may wish to withdraw from the network. To do so he must first deactivate his stake, and wait for cooldown. -The transaction must be signed by the stake's `authorized_staker`. - -- `account[0]` - RW - The StakeStateV2::Stake instance that is deactivating. -- `account[1]` - R - sysvar::clock account from the Bank that carries current epoch. - -StakeStateV2::Stake::deactivated is set to the current epoch + cooldown. The account's stake will ramp down to zero by that epoch, and Account::lamports will be available for withdrawal. - -### StakeInstruction::Withdraw\(u64\) - -Lamports build up over time in a Stake account and any excess over activated stake can be withdrawn. The transaction must be signed by the stake's `authorized_withdrawer`. - -- `account[0]` - RW - The StakeStateV2::Stake from which to withdraw. -- `account[1]` - RW - Account that should be credited with the withdrawn lamports. -- `account[2]` - R - sysvar::clock account from the Bank that carries current epoch, to calculate stake. -- `account[3]` - R - sysvar::stake_history account from the Bank that carries stake warmup/cooldown history. - -## Benefits of the design - -- Single vote for all the stakers. -- Clearing of the credit variable is not necessary for claiming rewards. -- Each delegated stake can claim its rewards independently. -- Commission for the work is deposited when a reward is claimed by the delegated stake. - -## Example Callflow - -![Passive Staking Callflow](/img/passive-staking-callflow.png) - -## Staking Rewards - -The specific mechanics and rules of the validator rewards regime is outlined here. Rewards are earned by delegating stake to a validator that is voting correctly. Voting incorrectly exposes that validator's stakes to [slashing](../proposals/slashing.md). - -### Basics - -The network pays rewards from a portion of network [inflation](../terminology.md#inflation). The number of lamports available to pay rewards for an epoch is fixed and must be evenly divided among all staked nodes according to their relative stake weight and participation. The weighting unit is called a [point](../terminology.md#point). - -Rewards for an epoch are not available until the end of that epoch. - -At the end of each epoch, the total number of points earned during the epoch is summed and used to divide the rewards portion of epoch inflation to arrive at a point value. This value is recorded in the bank in a [sysvar](../terminology.md#sysvar) that maps epochs to point values. - -During redemption, the stake program counts the points earned by the stake for each epoch, multiplies that by the epoch's point value, and transfers lamports in that amount from a rewards account into the stake and vote accounts according to the vote account's commission setting. - -### Economics - -Point value for an epoch depends on aggregate network participation. If participation in an epoch drops off, point values are higher for those that do participate. - -### Earning credits - -Validators earn one vote credit for every correct vote that exceeds maximum lockout, i.e. every time the validator's vote account retires a slot from its lockout list, making that vote a root for the node. - -Stakers who have delegated to that validator earn points in proportion to their stake. Points earned is the product of vote credits and stake. - -### Stake warmup, cooldown, withdrawal - -Stakes, once delegated, do not become effective immediately. They must first pass through a warmup period. During this period some portion of the stake is considered "effective", the rest is considered "activating". Changes occur on epoch boundaries. - -The stake program limits the rate of change to total network stake, reflected in the stake program's `config::warmup_rate` \(set to 25% per epoch in the current implementation\). - -The amount of stake that can be warmed up each epoch is a function of the previous epoch's total effective stake, total activating stake, and the stake program's configured warmup rate. - -Cooldown works the same way. Once a stake is deactivated, some part of it is considered "effective", and also "deactivating". As the stake cools down, it continues to earn rewards and be exposed to slashing, but it also becomes available for withdrawal. - -Bootstrap stakes are not subject to warmup. - -Rewards are paid against the "effective" portion of the stake for that epoch. - -#### Warmup example - -Consider the situation of a single stake of 1,000 activated at epoch N, with network warmup rate of 20%, and a quiescent total network stake at epoch N of 2,000. - -At epoch N+1, the amount available to be activated for the network is 400 \(20% of 2000\), and at epoch N, this example stake is the only stake activating, and so is entitled to all of the warmup room available. - -| epoch | effective | activating | total effective | total activating | -| :---- | --------: | ---------: | --------------: | ---------------: | -| N-1 | | | 2,000 | 0 | -| N | 0 | 1,000 | 2,000 | 1,000 | -| N+1 | 400 | 600 | 2,400 | 600 | -| N+2 | 880 | 120 | 2,880 | 120 | -| N+3 | 1000 | 0 | 3,000 | 0 | - -Were 2 stakes \(X and Y\) to activate at epoch N, they would be awarded a portion of the 20% in proportion to their stakes. At each epoch effective and activating for each stake is a function of the previous epoch's state. - -| epoch | X eff | X act | Y eff | Y act | total effective | total activating | -| :---- | ----: | ----: | ----: | ----: | --------------: | ---------------: | -| N-1 | | | | | 2,000 | 0 | -| N | 0 | 1,000 | 0 | 200 | 2,000 | 1,200 | -| N+1 | 333 | 667 | 67 | 133 | 2,400 | 800 | -| N+2 | 733 | 267 | 146 | 54 | 2,880 | 321 | -| N+3 | 1000 | 0 | 200 | 0 | 3,200 | 0 | - -### Withdrawal - -Only lamports in excess of effective+activating stake may be withdrawn at any time. This means that during warmup, effectively no stake can be withdrawn. During cooldown, any tokens in excess of effective stake may be withdrawn \(activating == 0\). Because earned rewards are automatically added to stake, withdrawal is generally only possible after deactivation. - -### Lock-up - -Stake accounts support the notion of lock-up, wherein the stake account balance is unavailable for withdrawal until a specified time. Lock-up is specified as an epoch height, i.e. the minimum epoch height that must be reached by the network before the stake account balance is available for withdrawal, unless the transaction is also signed by a specified custodian. This information is gathered when the stake account is created, and stored in the Lockup field of the stake account's state. Changing the authorized staker or withdrawer is also subject to lock-up, as such an operation is effectively a transfer. diff --git a/docs/src/clusters.md b/docs/src/clusters/available.md similarity index 94% rename from docs/src/clusters.md rename to docs/src/clusters/available.md index 5d59e7ea6c..7abfb06880 100644 --- a/docs/src/clusters.md +++ b/docs/src/clusters/available.md @@ -5,7 +5,7 @@ title: Solana Clusters Solana maintains several different clusters with different purposes. Before you begin make sure you have first -[installed the Solana command line tools](cli/install-solana-cli-tools.md) +[installed the Solana command line tools](../cli/install.md) Explorers: @@ -63,7 +63,7 @@ $ solana-validator \ --limit-ledger-size ``` -The [`--known-validator`s](running-validator/validator-start.md#known-validators) +The [`--known-validator`s](../operations/guides/validator-start.md#known-validators) are operated by Solana Labs ## Testnet @@ -115,7 +115,7 @@ $ solana-validator \ ``` The identities of the -[`--known-validator`s](running-validator/validator-start.md#known-validators) are: +[`--known-validator`s](../operations/guides/validator-start.md#known-validators) are: - `5D1fNXzvv5NjV1ysLjirC4WY92RNsVH18vjmcszZd8on` - Solana Labs - `dDzy5SR3AXdYWVqbDEkVFdvSPCtS9ihF5kJkHCtXoFs` - MonkeDAO @@ -168,5 +168,7 @@ $ solana-validator \ --limit-ledger-size ``` -All four [`--known-validator`s](running-validator/validator-start.md#known-validators) -are operated by Solana Labs +:::info +The above four [`--known-validator`s](../operations/guides/validator-start.md#known-validators) +are operated by Solana Labs. +::: \ No newline at end of file diff --git a/docs/src/cluster/bench-tps.md b/docs/src/clusters/benchmark.md similarity index 100% rename from docs/src/cluster/bench-tps.md rename to docs/src/clusters/benchmark.md diff --git a/docs/src/cluster/overview.md b/docs/src/clusters/index.md similarity index 98% rename from docs/src/cluster/overview.md rename to docs/src/clusters/index.md index 0fbdd53859..8ac1dee11d 100644 --- a/docs/src/cluster/overview.md +++ b/docs/src/clusters/index.md @@ -1,5 +1,7 @@ --- title: A Solana Cluster +sidebar_label: Overview +sidebar_position: 0 --- A Solana cluster is a set of validators working together to serve client transactions and maintain the integrity of the ledger. Many clusters may coexist. When two clusters share a common genesis block, they attempt to converge. Otherwise, they simply ignore the existence of the other. Transactions sent to the wrong one are quietly rejected. In this section, we'll discuss how a cluster is created, how nodes join the cluster, how they share the ledger, how they ensure the ledger is replicated, and how they cope with buggy and malicious nodes. @@ -36,4 +38,4 @@ Solana rotates leaders at fixed intervals, called _slots_. Each leader may only Next, transactions are broken into batches so that a node can send transactions to multiple parties without making multiple copies. If, for example, the leader needed to send 60 transactions to 6 nodes, it would break that collection of 60 into batches of 10 transactions and send one to each node. This allows the leader to put 60 transactions on the wire, not 60 transactions for each node. Each node then shares its batch with its peers. Once the node has collected all 6 batches, it reconstructs the original set of 60 transactions. -A batch of transactions can only be split so many times before it is so small that header information becomes the primary consumer of network bandwidth. At the time of this writing (December, 2021), the approach is scaling well up to about 1,250 validators. To scale up to hundreds of thousands of validators, each node can apply the same technique as the leader node to another set of nodes of equal size. We call the technique [_Turbine Block Propagation_](turbine-block-propagation.md). +A batch of transactions can only be split so many times before it is so small that header information becomes the primary consumer of network bandwidth. At the time of this writing (December, 2021), the approach is scaling well up to about 1,250 validators. To scale up to hundreds of thousands of validators, each node can apply the same technique as the leader node to another set of nodes of equal size. We call the technique [_Turbine Block Propagation_](../consensus/turbine-block-propagation.md). diff --git a/docs/src/cluster/performance-metrics.md b/docs/src/clusters/metrics.md similarity index 100% rename from docs/src/cluster/performance-metrics.md rename to docs/src/clusters/metrics.md diff --git a/docs/src/cluster/commitments.md b/docs/src/consensus/commitments.md similarity index 66% rename from docs/src/cluster/commitments.md rename to docs/src/consensus/commitments.md index 6b7edd1c21..0bfb55e923 100644 --- a/docs/src/cluster/commitments.md +++ b/docs/src/consensus/commitments.md @@ -1,6 +1,8 @@ --- title: Commitment Status -description: "Processed, confirmed, and finalized. Learn the differences between the different commitment statuses on the Solana blockchain." +description: + "Processed, confirmed, and finalized. Learn the differences between the + different commitment statuses on the Solana blockchain." keywords: - processed - confirmed @@ -10,7 +12,9 @@ keywords: - blockhash --- -The [commitment](./../terminology.md#commitment) metric gives clients a standard measure of the network confirmation for the block. Clients can then use this information to derive their own measures of commitment. +The [commitment](https://solana.com/docs/terminology#commitment) metric gives +clients a standard measure of the network confirmation for the block. Clients +can then use this information to derive their own measures of commitment. There are three specific commitment statuses: diff --git a/docs/src/consensus/fork-generation.md b/docs/src/consensus/fork-generation.md new file mode 100644 index 0000000000..6008c6c07a --- /dev/null +++ b/docs/src/consensus/fork-generation.md @@ -0,0 +1,139 @@ +--- +title: Fork Generation +description: + "A fork is created when validators do not agree on a newly produced block. + Using a consensus algorithm validators vote on which will be finalized." +--- + +The Solana protocol doesn’t wait for all validators to agree on a newly produced +block before the next block is produced. Because of that, it’s quite common for +two different blocks to be chained to the same parent block. In those +situations, we call each conflicting chain a [“fork.”](./fork-generation.md) + +Solana validators need to vote on one of these forks and reach agreement on +which one to use through a consensus algorithm (that is beyond the scope of this +article). The main point you need to remember is that when there are competing +forks, only one fork will be finalized by the cluster and the abandoned blocks +in competing forks are all discarded. + +This section describes how forks naturally occur as a consequence of +[leader rotation](./leader-rotation.md). + +## Overview + +Nodes take turns being [leader](https://solana.com/docs/terminology#leader) and +generating the PoH that encodes state changes. The cluster can tolerate loss of +connection to any leader by synthesizing what the leader _**would**_ have +generated had it been connected but not ingesting any state changes. + +The possible number of forks is thereby limited to a "there/not-there" skip list +of forks that may arise on leader rotation slot boundaries. At any given slot, +only a single leader's transactions will be accepted. + +### Forking example + +The table below illustrates what competing forks could look like. Time +progresses from left to right and each slot is assigned to a validator that +temporarily becomes the cluster “leader” and may produce a block for that slot. + +In this example, the leader for slot 3 chose to chain its “Block 3” directly to +“Block 1” and in doing so skipped “Block 2”. Similarly, the leader for slot 5 +chose to chain “Block 5” directly to “Block 3” and skipped “Block 4”. + +> Note that across different forks, the block produced for a given slot is +> _always_ the same because producing two different blocks for the same slot is +> a slashable offense. So the conflicting forks above can be distinguished from +> each other by which slots they have _skipped_. + +| | Slot 1 | Slot 2 | Slot 3 | Slot 4 | Slot 5 | +| ------ | ------- | ------- | ------- | ------- | ------- | +| Fork 1 | Block 1 | | Block 3 | | Block 5 | +| Fork 2 | Block 1 | | Block 3 | Block 4 | | +| Fork 3 | Block 1 | Block 2 | | | | + +## Message Flow + +1. Transactions are ingested by the current leader. +2. Leader filters valid transactions. +3. Leader executes valid transactions updating its state. +4. Leader packages transactions into entries based off its current PoH slot. +5. Leader transmits the entries to validator nodes \(in signed shreds\) + 1. The PoH stream includes ticks; empty entries that indicate liveness of the + leader and the passage of time on the cluster. + 2. A leader's stream begins with the tick entries necessary to complete PoH + back to the leader's most recently observed prior leader slot. +6. Validators retransmit entries to peers in their set and to further downstream + nodes. +7. Validators validate the transactions and execute them on their state. +8. Validators compute the hash of the state. +9. At specific times, i.e. specific PoH tick counts, validators transmit votes + to the leader. + 1. Votes are signatures of the hash of the computed state at that PoH tick + count. + 2. Votes are also propagated via gossip. +10. Leader executes the votes, the same as any other transaction, and broadcasts + them to the cluster. +11. Validators observe their votes and all the votes from the cluster. + +## Partitions, Forks + +Forks can arise at PoH tick counts that correspond to a vote. The next leader +may not have observed the last vote slot and may start their slot with generated +virtual PoH entries. These empty ticks are generated by all nodes in the cluster +at a cluster-configured rate for hashes/per/tick `Z`. + +There are only two possible versions of the PoH during a voting slot: PoH with +`T` ticks and entries generated by the current leader, or PoH with just ticks. +The "just ticks" version of the PoH can be thought of as a virtual ledger, one +that all nodes in the cluster can derive from the last tick in the previous +slot. + +Validators can ignore forks at other points \(e.g. from the wrong leader\), or +slash the leader responsible for the fork. + +Validators vote based on a greedy choice to maximize their reward described in +[Tower BFT](../implemented-proposals/tower-bft.md). + +### Validator's View + +#### Time Progression + +The diagram below represents a validator's view of the PoH stream with possible +forks over time. L1, L2, etc. are leader slots, and `E`s represent entries from +that leader during that leader's slot. The `x`s represent ticks only, and time +flows downwards in the diagram. + +![Fork generation](/img/fork-generation.svg) + +Note that an `E` appearing on 2 forks at the same slot is a slashable condition, +so a validator observing `E3` and `E3'` can slash L3 and safely choose `x` for +that slot. Once a validator commits to a fork, other forks can be discarded +below that tick count. For any slot, validators need only consider a single "has +entries" chain or a "ticks only" chain to be proposed by a leader. But multiple +virtual entries may overlap as they link back to the a previous slot. + +#### Time Division + +It's useful to consider leader rotation over PoH tick count as time division of +the job of encoding state for the cluster. The following table presents the +above tree of forks as a time-divided ledger. + +| leader slot | L1 | L2 | L3 | L4 | L5 | +| :--------------- | :-- | :-- | :-- | :-- | :-- | +| data | E1 | E2 | E3 | E4 | E5 | +| ticks since prev | | | | x | xx | + +Note that only data from leader L3 will be accepted during leader slot L3. Data +from L3 may include "catchup" ticks back to a slot other than L2 if L3 did not +observe L2's data. L4 and L5's transmissions include the "ticks to prev" PoH +entries. + +This arrangement of the network data streams permits nodes to save exactly this +to the ledger for replay, restart, and checkpoints. + +### Leader's View + +When a new leader begins a slot, it must first transmit any PoH \(ticks\) +required to link the new slot with the most recently observed and voted slot. +The fork the leader proposes would link the current slot to a previous fork that +the leader has voted on with virtual ticks. diff --git a/docs/src/cluster/leader-rotation.md b/docs/src/consensus/leader-rotation.md similarity index 100% rename from docs/src/cluster/leader-rotation.md rename to docs/src/consensus/leader-rotation.md diff --git a/docs/src/cluster/managing-forks.md b/docs/src/consensus/managing-forks.md similarity index 100% rename from docs/src/cluster/managing-forks.md rename to docs/src/consensus/managing-forks.md diff --git a/docs/src/consensus/stake-delegation-and-rewards.md b/docs/src/consensus/stake-delegation-and-rewards.md new file mode 100644 index 0000000000..72f29d5c0c --- /dev/null +++ b/docs/src/consensus/stake-delegation-and-rewards.md @@ -0,0 +1,339 @@ +--- +title: Stake Delegation and Rewards +--- + +Stakers are rewarded for helping to validate the ledger. They do this by +delegating their stake to validator nodes. Those validators do the legwork of +replaying the ledger and sending votes to a per-node vote account to which +stakers can delegate their stakes. The rest of the cluster uses those +stake-weighted votes to select a block when forks arise. Both the validator and +staker need some economic incentive to play their part. The validator needs to +be compensated for its hardware and the staker needs to be compensated for the +risk of getting its stake slashed. The economics are covered in +[staking rewards](../implemented-proposals/staking-rewards.md). This section, on +the other hand, describes the underlying mechanics of its implementation. + +## Basic Design + +The general idea is that the validator owns a Vote account. The Vote account +tracks validator votes, counts validator generated credits, and provides any +additional validator specific state. The Vote account is not aware of any stakes +delegated to it and has no staking weight. + +A separate Stake account \(created by a staker\) names a Vote account to which +the stake is delegated. Rewards generated are proportional to the amount of +lamports staked. The Stake account is owned by the staker only. Some portion of +the lamports stored in this account are the stake. + +## Passive Delegation + +Any number of Stake accounts can delegate to a single Vote account without an +interactive action from the identity controlling the Vote account or submitting +votes to the account. + +The total stake allocated to a Vote account can be calculated by the sum of all +the Stake accounts that have the Vote account pubkey as the +`StakeStateV2::Stake::voter_pubkey`. + +## Vote and Stake accounts + +The rewards process is split into two on-chain programs. The Vote program solves +the problem of making stakes slashable. The Stake program acts as custodian of +the rewards pool and provides for passive delegation. The Stake program is +responsible for paying rewards to staker and voter when shown that a staker's +delegate has participated in validating the ledger. + +### VoteState + +VoteState is the current state of all the votes the validator has submitted to +the network. VoteState contains the following state information: + +- `votes` - The submitted votes data structure. +- `credits` - The total number of rewards this Vote program has generated over + its lifetime. +- `root_slot` - The last slot to reach the full lockout commitment necessary for + rewards. +- `commission` - The commission taken by this VoteState for any rewards claimed + by staker's Stake accounts. This is the percentage ceiling of the reward. +- Account::lamports - The accumulated lamports from the commission. These do not + count as stakes. +- `authorized_voter` - Only this identity is authorized to submit votes. This + field can only modified by this identity. +- `node_pubkey` - The Solana node that votes in this account. +- `authorized_withdrawer` - the identity of the entity in charge of the lamports + of this account, separate from the account's address and the authorized vote + signer. + +### VoteInstruction::Initialize\(VoteInit\) + +- `account[0]` - RW - The VoteState. + + `VoteInit` carries the new vote account's `node_pubkey`, `authorized_voter`, + `authorized_withdrawer`, and `commission`. + + other VoteState members defaulted. + +### VoteInstruction::Authorize\(Pubkey, VoteAuthorize\) + +Updates the account with a new authorized voter or withdrawer, according to the +VoteAuthorize parameter \(`Voter` or `Withdrawer`\). The transaction must be +signed by the Vote account's current `authorized_voter` or +`authorized_withdrawer`. + +- `account[0]` - RW - The VoteState. `VoteState::authorized_voter` or + `authorized_withdrawer` is set to `Pubkey`. + +### VoteInstruction::AuthorizeWithSeed\(VoteAuthorizeWithSeedArgs\) + +Updates the account with a new authorized voter or withdrawer, according to the +VoteAuthorize parameter \(`Voter` or `Withdrawer`\). Unlike +`VoteInstruction::Authorize` this instruction is for use when the Vote account's +current `authorized_voter` or `authorized_withdrawer` is a derived key. The +transaction must be signed by someone who can sign for the base key of that +derived key. + +- `account[0]` - RW - The VoteState. `VoteState::authorized_voter` or + `authorized_withdrawer` is set to `Pubkey`. + +### VoteInstruction::Vote\(Vote\) + +- `account[0]` - RW - The VoteState. `VoteState::lockouts` and + `VoteState::credits` are updated according to voting lockout rules see + [Tower BFT](../implemented-proposals/tower-bft.md). +- `account[1]` - RO - `sysvar::slot_hashes` A list of some N most recent slots + and their hashes for the vote to be verified against. +- `account[2]` - RO - `sysvar::clock` The current network time, expressed in + slots, epochs. + +### StakeStateV2 + +A StakeStateV2 takes one of four forms, StakeStateV2::Uninitialized, +StakeStateV2::Initialized, StakeStateV2::Stake, and StakeStateV2::RewardsPool. +Only the first three forms are used in staking, but only StakeStateV2::Stake is +interesting. All RewardsPools are created at genesis. + +### StakeStateV2::Stake + +StakeStateV2::Stake is the current delegation preference of the **staker** and +contains the following state information: + +- Account::lamports - The lamports available for staking. +- `stake` - the staked amount \(subject to warmup and cooldown\) for generating + rewards, always less than or equal to Account::lamports. +- `voter_pubkey` - The pubkey of the VoteState instance the lamports are + delegated to. +- `credits_observed` - The total credits claimed over the lifetime of the + program. +- `activated` - the epoch at which this stake was activated/delegated. The full + stake will be counted after warmup. +- `deactivated` - the epoch at which this stake was de-activated, some cooldown + epochs are required before the account is fully deactivated, and the stake + available for withdrawal. +- `authorized_staker` - the pubkey of the entity that must sign delegation, + activation, and deactivation transactions. +- `authorized_withdrawer` - the identity of the entity in charge of the lamports + of this account, separate from the account's address, and the authorized + staker. + +### StakeStateV2::RewardsPool + +To avoid a single network-wide lock or contention in redemption, 256 +RewardsPools are part of genesis under pre-determined keys, each with +std::u64::MAX credits to be able to satisfy redemptions according to point +value. + +The Stakes and the RewardsPool are accounts that are owned by the same `Stake` +program. + +### StakeInstruction::DelegateStake + +The Stake account is moved from Initialized to StakeStateV2::Stake form, or from +a deactivated (i.e. fully cooled-down) StakeStateV2::Stake to activated +StakeStateV2::Stake. This is how stakers choose the vote account and validator +node to which their stake account lamports are delegated. The transaction must +be signed by the stake's `authorized_staker`. + +- `account[0]` - RW - The StakeStateV2::Stake instance. + `StakeStateV2::Stake::credits_observed` is initialized to + `VoteState::credits`, `StakeStateV2::Stake::voter_pubkey` is initialized to + `account[1]`. If this is the initial delegation of stake, + `StakeStateV2::Stake::stake` is initialized to the account's balance in + lamports, `StakeStateV2::Stake::activated` is initialized to the current Bank + epoch, and `StakeStateV2::Stake::deactivated` is initialized to std::u64::MAX +- `account[1]` - R - The VoteState instance. +- `account[2]` - R - sysvar::clock account, carries information about current + Bank epoch. +- `account[3]` - R - sysvar::stakehistory account, carries information about + stake history. +- `account[4]` - R - stake::Config account, carries warmup, cooldown, and + slashing configuration. + +### StakeInstruction::Authorize\(Pubkey, StakeAuthorize\) + +Updates the account with a new authorized staker or withdrawer, according to the +StakeAuthorize parameter \(`Staker` or `Withdrawer`\). The transaction must be +by signed by the Stakee account's current `authorized_staker` or +`authorized_withdrawer`. Any stake lock-up must have expired, or the lock-up +custodian must also sign the transaction. + +- `account[0]` - RW - The StakeStateV2. + + `StakeStateV2::authorized_staker` or `authorized_withdrawer` is set to to + `Pubkey`. + +### StakeInstruction::Deactivate + +A staker may wish to withdraw from the network. To do so he must first +deactivate his stake, and wait for cooldown. The transaction must be signed by +the stake's `authorized_staker`. + +- `account[0]` - RW - The StakeStateV2::Stake instance that is deactivating. +- `account[1]` - R - sysvar::clock account from the Bank that carries current + epoch. + +StakeStateV2::Stake::deactivated is set to the current epoch + cooldown. The +account's stake will ramp down to zero by that epoch, and Account::lamports will +be available for withdrawal. + +### StakeInstruction::Withdraw\(u64\) + +Lamports build up over time in a Stake account and any excess over activated +stake can be withdrawn. The transaction must be signed by the stake's +`authorized_withdrawer`. + +- `account[0]` - RW - The StakeStateV2::Stake from which to withdraw. +- `account[1]` - RW - Account that should be credited with the withdrawn + lamports. +- `account[2]` - R - sysvar::clock account from the Bank that carries current + epoch, to calculate stake. +- `account[3]` - R - sysvar::stake_history account from the Bank that carries + stake warmup/cooldown history. + +## Benefits of the design + +- Single vote for all the stakers. +- Clearing of the credit variable is not necessary for claiming rewards. +- Each delegated stake can claim its rewards independently. +- Commission for the work is deposited when a reward is claimed by the delegated + stake. + +## Example Callflow + +![Passive Staking Callflow](/img/passive-staking-callflow.png) + +## Staking Rewards + +The specific mechanics and rules of the validator rewards regime is outlined +here. Rewards are earned by delegating stake to a validator that is voting +correctly. Voting incorrectly exposes that validator's stakes to +[slashing](../proposals/slashing.md). + +### Basics + +The network pays rewards from a portion of network +[inflation](https://solana.com/docs/terminology#inflation). The number of +lamports available to pay rewards for an epoch is fixed and must be evenly +divided among all staked nodes according to their relative stake weight and +participation. The weighting unit is called a +[point](https://solana.com/docs/terminology#point). + +Rewards for an epoch are not available until the end of that epoch. + +At the end of each epoch, the total number of points earned during the epoch is +summed and used to divide the rewards portion of epoch inflation to arrive at a +point value. This value is recorded in the bank in a +[sysvar](https://solana.com/docs/terminology#sysvar) that maps epochs to point +values. + +During redemption, the stake program counts the points earned by the stake for +each epoch, multiplies that by the epoch's point value, and transfers lamports +in that amount from a rewards account into the stake and vote accounts according +to the vote account's commission setting. + +### Economics + +Point value for an epoch depends on aggregate network participation. If +participation in an epoch drops off, point values are higher for those that do +participate. + +### Earning credits + +Validators earn one vote credit for every correct vote that exceeds maximum +lockout, i.e. every time the validator's vote account retires a slot from its +lockout list, making that vote a root for the node. + +Stakers who have delegated to that validator earn points in proportion to their +stake. Points earned is the product of vote credits and stake. + +### Stake warmup, cooldown, withdrawal + +Stakes, once delegated, do not become effective immediately. They must first +pass through a warmup period. During this period some portion of the stake is +considered "effective", the rest is considered "activating". Changes occur on +epoch boundaries. + +The stake program limits the rate of change to total network stake, reflected in +the stake program's `config::warmup_rate` \(set to 25% per epoch in the current +implementation\). + +The amount of stake that can be warmed up each epoch is a function of the +previous epoch's total effective stake, total activating stake, and the stake +program's configured warmup rate. + +Cooldown works the same way. Once a stake is deactivated, some part of it is +considered "effective", and also "deactivating". As the stake cools down, it +continues to earn rewards and be exposed to slashing, but it also becomes +available for withdrawal. + +Bootstrap stakes are not subject to warmup. + +Rewards are paid against the "effective" portion of the stake for that epoch. + +#### Warmup example + +Consider the situation of a single stake of 1,000 activated at epoch N, with +network warmup rate of 20%, and a quiescent total network stake at epoch N of +2,000. + +At epoch N+1, the amount available to be activated for the network is 400 \(20% +of 2000\), and at epoch N, this example stake is the only stake activating, and +so is entitled to all of the warmup room available. + +| epoch | effective | activating | total effective | total activating | +| :---- | --------: | ---------: | --------------: | ---------------: | +| N-1 | | | 2,000 | 0 | +| N | 0 | 1,000 | 2,000 | 1,000 | +| N+1 | 400 | 600 | 2,400 | 600 | +| N+2 | 880 | 120 | 2,880 | 120 | +| N+3 | 1000 | 0 | 3,000 | 0 | + +Were 2 stakes \(X and Y\) to activate at epoch N, they would be awarded a +portion of the 20% in proportion to their stakes. At each epoch effective and +activating for each stake is a function of the previous epoch's state. + +| epoch | X eff | X act | Y eff | Y act | total effective | total activating | +| :---- | ----: | ----: | ----: | ----: | --------------: | ---------------: | +| N-1 | | | | | 2,000 | 0 | +| N | 0 | 1,000 | 0 | 200 | 2,000 | 1,200 | +| N+1 | 333 | 667 | 67 | 133 | 2,400 | 800 | +| N+2 | 733 | 267 | 146 | 54 | 2,880 | 321 | +| N+3 | 1000 | 0 | 200 | 0 | 3,200 | 0 | + +### Withdrawal + +Only lamports in excess of effective+activating stake may be withdrawn at any +time. This means that during warmup, effectively no stake can be withdrawn. +During cooldown, any tokens in excess of effective stake may be withdrawn +\(activating == 0\). Because earned rewards are automatically added to stake, +withdrawal is generally only possible after deactivation. + +### Lock-up + +Stake accounts support the notion of lock-up, wherein the stake account balance +is unavailable for withdrawal until a specified time. Lock-up is specified as an +epoch height, i.e. the minimum epoch height that must be reached by the network +before the stake account balance is available for withdrawal, unless the +transaction is also signed by a specified custodian. This information is +gathered when the stake account is created, and stored in the Lockup field of +the stake account's state. Changing the authorized staker or withdrawer is also +subject to lock-up, as such an operation is effectively a transfer. diff --git a/docs/src/cluster/synchronization.md b/docs/src/consensus/synchronization.md similarity index 97% rename from docs/src/cluster/synchronization.md rename to docs/src/consensus/synchronization.md index bfde654f84..3eb763e4da 100644 --- a/docs/src/cluster/synchronization.md +++ b/docs/src/consensus/synchronization.md @@ -16,7 +16,7 @@ The Proof of History technique was first described for use in blockchain by Sola A desirable property of a VDF is that verification time is very fast. Solana's approach to verifying its delay function is proportional to the time it took to create it. Split over a 4000 core GPU, it is sufficiently fast for Solana's needs, but if you asked the authors of the paper cited above, they might tell you \([and have](https://github.com/solana-labs/solana/issues/388)\) that Solana's approach is algorithmically slow and it shouldn't be called a VDF. We argue the term VDF should represent the category of verifiable delay functions and not just the subset with certain performance characteristics. Until that's resolved, Solana will likely continue using the term PoH for its application-specific VDF. -Another difference between PoH and VDFs is that a VDF is used only for tracking duration. PoH's hash chain, on the other hand, includes hashes of any data the application observed. That data is a double-edged sword. On one side, the data "proves history" - that the data most certainly existed before hashes after it. On the other side, it means the application can manipulate the hash chain by changing _when_ the data is hashed. The PoH chain therefore does not serve as a good source of randomness whereas a VDF without that data could. Solana's [leader rotation algorithm](synchronization.md#leader-rotation), for example, is derived only from the VDF _height_ and not its hash at that height. +Another difference between PoH and VDFs is that a VDF is used only for tracking duration. PoH's hash chain, on the other hand, includes hashes of any data the application observed. That data is a double-edged sword. On one side, the data "proves history" - that the data most certainly existed before hashes after it. On the other side, it means the application can manipulate the hash chain by changing _when_ the data is hashed. The PoH chain therefore does not serve as a good source of randomness whereas a VDF without that data could. Solana's [leader rotation algorithm](./leader-rotation.md), for example, is derived only from the VDF _height_ and not its hash at that height. ## Relationship to Consensus Mechanisms diff --git a/docs/src/cluster/turbine-block-propagation.md b/docs/src/consensus/turbine-block-propagation.md similarity index 100% rename from docs/src/cluster/turbine-block-propagation.md rename to docs/src/consensus/turbine-block-propagation.md diff --git a/docs/src/cluster/vote-signing.md b/docs/src/consensus/vote-signing.md similarity index 100% rename from docs/src/cluster/vote-signing.md rename to docs/src/consensus/vote-signing.md diff --git a/docs/src/developing/clients/javascript-api.md b/docs/src/developing/clients/javascript-api.md deleted file mode 100644 index 8dad0f46a0..0000000000 --- a/docs/src/developing/clients/javascript-api.md +++ /dev/null @@ -1,341 +0,0 @@ ---- -title: Web3 JavaScript API ---- - -## What is Solana-Web3.js? - -The Solana-Web3.js library aims to provide complete coverage of Solana. The library was built on top of the [Solana JSON RPC API](/api). - -You can find the full documentation for the `@solana/web3.js` library [here](https://solana-labs.github.io/solana-web3.js/). - -## Common Terminology - -| Term | Definition | -| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Program | Stateless executable code written to interpret instructions. Programs are capable of performing actions based on the instructions provided. | -| Instruction | The smallest unit of a program that a client can include in a transaction. Within its processing code, an instruction may contain one or more cross-program invocations. | -| Transaction | One or more instructions signed by the client using one or more Keypairs and executed atomically with only two possible outcomes: success or failure. | - -For the full list of terms, see [Solana terminology](../../terminology#cross-program-invocation) - -## Getting Started - -### Installation - -#### yarn - -```bash -$ yarn add @solana/web3.js -``` - -#### npm - -```bash -$ npm install --save @solana/web3.js -``` - -#### Bundle - -```html - - - - - -``` - -### Usage - -#### Javascript - -```javascript -const solanaWeb3 = require("@solana/web3.js"); -console.log(solanaWeb3); -``` - -#### ES6 - -```javascript -import * as solanaWeb3 from "@solana/web3.js"; -console.log(solanaWeb3); -``` - -#### Browser Bundle - -```javascript -// solanaWeb3 is provided in the global namespace by the bundle script -console.log(solanaWeb3); -``` - -## Quickstart - -### Connecting to a Wallet - -To allow users to use your dApp or application on Solana, they will need to get access to their Keypair. A Keypair is a private key with a matching public key, used to sign transactions. - -There are two ways to obtain a Keypair: - -1. Generate a new Keypair -2. Obtain a Keypair using the secret key - -You can obtain a new Keypair with the following: - -```javascript -const { Keypair } = require("@solana/web3.js"); - -let keypair = Keypair.generate(); -``` - -This will generate a brand new Keypair for a user to fund and use within your application. - -You can allow entry of the secretKey using a textbox, and obtain the Keypair with `Keypair.fromSecretKey(secretKey)`. - -```javascript -const { Keypair } = require("@solana/web3.js"); - -let secretKey = Uint8Array.from([ - 202, 171, 192, 129, 150, 189, 204, 241, 142, 71, 205, 2, 81, 97, 2, 176, 48, - 81, 45, 1, 96, 138, 220, 132, 231, 131, 120, 77, 66, 40, 97, 172, 91, 245, 84, - 221, 157, 190, 9, 145, 176, 130, 25, 43, 72, 107, 190, 229, 75, 88, 191, 136, - 7, 167, 109, 91, 170, 164, 186, 15, 142, 36, 12, 23, -]); - -let keypair = Keypair.fromSecretKey(secretKey); -``` - -Many wallets today allow users to bring their Keypair using a variety of extensions or web wallets. The general recommendation is to use wallets, not Keypairs, to sign transactions. The wallet creates a layer of separation between the dApp and the Keypair, ensuring that the dApp never has access to the secret key. You can find ways to connect to external wallets with the [wallet-adapter](https://github.com/solana-labs/wallet-adapter) library. - -### Creating and Sending Transactions - -To interact with programs on Solana, you create, sign, and send transactions to the network. Transactions are collections of instructions with signatures. The order that instructions exist in a transaction determines the order they are executed. - -A transaction in Solana-Web3.js is created using the [`Transaction`](javascript-api.md#Transaction) object and adding desired messages, addresses, or instructions. - -Take the example of a transfer transaction: - -```javascript -const { - Keypair, - Transaction, - SystemProgram, - LAMPORTS_PER_SOL, -} = require("@solana/web3.js"); - -let fromKeypair = Keypair.generate(); -let toKeypair = Keypair.generate(); -let transaction = new Transaction(); - -transaction.add( - SystemProgram.transfer({ - fromPubkey: fromKeypair.publicKey, - toPubkey: toKeypair.publicKey, - lamports: LAMPORTS_PER_SOL, - }), -); -``` - -The above code achieves creating a transaction ready to be signed and broadcasted to the network. The `SystemProgram.transfer` instruction was added to the transaction, containing the amount of lamports to send, and the `to` and `from` public keys. - -All that is left is to sign the transaction with keypair and send it over the network. You can accomplish sending a transaction by using `sendAndConfirmTransaction` if you wish to alert the user or do something after a transaction is finished, or use `sendTransaction` if you don't need to wait for the transaction to be confirmed. - -```javascript -const { - sendAndConfirmTransaction, - clusterApiUrl, - Connection, -} = require("@solana/web3.js"); - -let keypair = Keypair.generate(); -let connection = new Connection(clusterApiUrl("testnet")); - -sendAndConfirmTransaction(connection, transaction, [keypair]); -``` - -The above code takes in a `TransactionInstruction` using `SystemProgram`, creates a `Transaction`, and sends it over the network. You use `Connection` in order to define which Solana network you are connecting to, namely `mainnet-beta`, `testnet`, or `devnet`. - -### Interacting with Custom Programs - -The previous section visits sending basic transactions. In Solana everything you do interacts with different programs, including the previous section's transfer transaction. At the time of writing programs on Solana are either written in Rust or C. - -Let's look at the `SystemProgram`. The method signature for allocating space in your account on Solana in Rust looks like this: - -```rust -pub fn allocate( - pubkey: &Pubkey, - space: u64 -) -> Instruction -``` - -In Solana when you want to interact with a program you must first know all the accounts you will be interacting with. - -You must always provide every account that the program will be interacting within the instruction. Not only that, but you must provide whether or not the account is `isSigner` or `isWritable`. - -In the `allocate` method above, a single account `pubkey` is required, as well as an amount of `space` for allocation. We know that the `allocate` method writes to the account by allocating space within it, making the `pubkey` required to be `isWritable`. `isSigner` is required when you are designating the account that is running the instruction. In this case, the signer is the account calling to allocate space within itself. - -Let's look at how to call this instruction using solana-web3.js: - -```javascript -let keypair = web3.Keypair.generate(); -let payer = web3.Keypair.generate(); -let connection = new web3.Connection(web3.clusterApiUrl("testnet")); - -let airdropSignature = await connection.requestAirdrop( - payer.publicKey, - web3.LAMPORTS_PER_SOL, -); - -await connection.confirmTransaction({ signature: airdropSignature }); -``` - -First, we set up the account Keypair and connection so that we have an account to make allocate on the testnet. We also create a payer Keypair and airdrop some sol so we can pay for the allocate transaction. - -```javascript -let allocateTransaction = new web3.Transaction({ - feePayer: payer.publicKey, -}); -let keys = [{ pubkey: keypair.publicKey, isSigner: true, isWritable: true }]; -let params = { space: 100 }; -``` - -We create the transaction `allocateTransaction`, keys, and params objects. `feePayer` is an optional field when creating a transaction that specifies who is paying for the transaction, defaulting to the pubkey of the first signer in the transaction. `keys` represents all accounts that the program's `allocate` function will interact with. Since the `allocate` function also required space, we created `params` to be used later when invoking the `allocate` function. - -```javascript -let allocateStruct = { - index: 8, - layout: struct([u32("instruction"), ns64("space")]), -}; -``` - -The above is created using `u32` and `ns64` from `@solana/buffer-layout` to facilitate the payload creation. The `allocate` function takes in the parameter `space`. To interact with the function we must provide the data as a Buffer format. The `buffer-layout` library helps with allocating the buffer and encoding it correctly for Rust programs on Solana to interpret. - -Let's break down this struct. - -```javascript -{ - index: 8, /* <-- */ - layout: struct([ - u32('instruction'), - ns64('space'), - ]) -} -``` - -`index` is set to 8 because the function `allocate` is in the 8th position in the instruction enum for `SystemProgram`. - -```rust -/* https://github.com/solana-labs/solana/blob/21bc43ed58c63c827ba4db30426965ef3e807180/sdk/program/src/system_instruction.rs#L142-L305 */ -pub enum SystemInstruction { - /** 0 **/CreateAccount {/**/}, - /** 1 **/Assign {/**/}, - /** 2 **/Transfer {/**/}, - /** 3 **/CreateAccountWithSeed {/**/}, - /** 4 **/AdvanceNonceAccount, - /** 5 **/WithdrawNonceAccount(u64), - /** 6 **/InitializeNonceAccount(Pubkey), - /** 7 **/AuthorizeNonceAccount(Pubkey), - /** 8 **/Allocate {/**/}, - /** 9 **/AllocateWithSeed {/**/}, - /** 10 **/AssignWithSeed {/**/}, - /** 11 **/TransferWithSeed {/**/}, - /** 12 **/UpgradeNonceAccount, -} -``` - -Next up is `u32('instruction')`. - -```javascript -{ - index: 8, - layout: struct([ - u32('instruction'), /* <-- */ - ns64('space'), - ]) -} -``` - -The `layout` in the allocate struct must always have `u32('instruction')` first when you are using it to call an instruction. - -```javascript -{ - index: 8, - layout: struct([ - u32('instruction'), - ns64('space'), /* <-- */ - ]) -} -``` - -`ns64('space')` is the argument for the `allocate` function. You can see in the original `allocate` function in Rust that space was of the type `u64`. `u64` is an unsigned 64bit integer. Javascript by default only provides up to 53bit integers. `ns64` comes from `@solana/buffer-layout` to help with type conversions between Rust and Javascript. You can find more type conversions between Rust and Javascript at [solana-labs/buffer-layout](https://github.com/solana-labs/buffer-layout). - -```javascript -let data = Buffer.alloc(allocateStruct.layout.span); -let layoutFields = Object.assign({ instruction: allocateStruct.index }, params); -allocateStruct.layout.encode(layoutFields, data); -``` - -Using the previously created bufferLayout, we can allocate a data buffer. We then assign our params `{ space: 100 }` so that it maps correctly to the layout, and encode it to the data buffer. Now the data is ready to be sent to the program. - -```javascript -allocateTransaction.add( - new web3.TransactionInstruction({ - keys, - programId: web3.SystemProgram.programId, - data, - }), -); - -await web3.sendAndConfirmTransaction(connection, allocateTransaction, [ - payer, - keypair, -]); -``` - -Finally, we add the transaction instruction with all the account keys, payer, data, and programId and broadcast the transaction to the network. - -The full code can be found below. - -```javascript -const { struct, u32, ns64 } = require("@solana/buffer-layout"); -const { Buffer } = require("buffer"); -const web3 = require("@solana/web3.js"); - -let keypair = web3.Keypair.generate(); -let payer = web3.Keypair.generate(); - -let connection = new web3.Connection(web3.clusterApiUrl("testnet")); - -let airdropSignature = await connection.requestAirdrop( - payer.publicKey, - web3.LAMPORTS_PER_SOL, -); - -await connection.confirmTransaction({ signature: airdropSignature }); - -let allocateTransaction = new web3.Transaction({ - feePayer: payer.publicKey, -}); -let keys = [{ pubkey: keypair.publicKey, isSigner: true, isWritable: true }]; -let params = { space: 100 }; - -let allocateStruct = { - index: 8, - layout: struct([u32("instruction"), ns64("space")]), -}; - -let data = Buffer.alloc(allocateStruct.layout.span); -let layoutFields = Object.assign({ instruction: allocateStruct.index }, params); -allocateStruct.layout.encode(layoutFields, data); - -allocateTransaction.add( - new web3.TransactionInstruction({ - keys, - programId: web3.SystemProgram.programId, - data, - }), -); - -await web3.sendAndConfirmTransaction(connection, allocateTransaction, [ - payer, - keypair, -]); -``` diff --git a/docs/src/developing/clients/javascript-reference.md b/docs/src/developing/clients/javascript-reference.md deleted file mode 100644 index bd13d64296..0000000000 --- a/docs/src/developing/clients/javascript-reference.md +++ /dev/null @@ -1,802 +0,0 @@ ---- -title: Web3 API Reference ---- - -## Web3 API Reference Guide - -The `@solana/web3.js` library is a package that has coverage over the [Solana JSON RPC API](/api). - -You can find the full documentation for the `@solana/web3.js` library [here](https://solana-labs.github.io/solana-web3.js/). - -## General - -### Connection - -[Source Documentation](https://solana-labs.github.io/solana-web3.js/classes/Connection.html) - -Connection is used to interact with the [Solana JSON RPC](/api). You can use Connection to confirm transactions, get account info, and more. - -You create a connection by defining the JSON RPC cluster endpoint and the desired commitment. Once this is complete, you can use this connection object to interact with any of the Solana JSON RPC API. - -#### Example Usage - -```javascript -const web3 = require("@solana/web3.js"); - -let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); - -let slot = await connection.getSlot(); -console.log(slot); -// 93186439 - -let blockTime = await connection.getBlockTime(slot); -console.log(blockTime); -// 1630747045 - -let block = await connection.getBlock(slot); -console.log(block); - -/* -{ - blockHeight: null, - blockTime: 1630747045, - blockhash: 'AsFv1aV5DGip9YJHHqVjrGg6EKk55xuyxn2HeiN9xQyn', - parentSlot: 93186438, - previousBlockhash: '11111111111111111111111111111111', - rewards: [], - transactions: [] -} -*/ - -let slotLeader = await connection.getSlotLeader(); -console.log(slotLeader); -//49AqLYbpJYc2DrzGUAH1fhWJy62yxBxpLEkfJwjKy2jr -``` - -The above example shows only a few of the methods on Connection. Please see the [source generated docs](https://solana-labs.github.io/solana-web3.js/classes/Connection.html) for the full list. - -### Transaction - -[SourceDocumentation](https://solana-labs.github.io/solana-web3.js/classes/Transaction.html) - -A transaction is used to interact with programs on the Solana blockchain. These transactions are constructed with TransactionInstructions, containing all the accounts possible to interact with, as well as any needed data or program addresses. Each TransactionInstruction consists of keys, data, and a programId. You can do multiple instructions in a single transaction, interacting with multiple programs at once. - -#### Example Usage - -```javascript -const web3 = require("@solana/web3.js"); -const nacl = require("tweetnacl"); - -// Airdrop SOL for paying transactions -let payer = web3.Keypair.generate(); -let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); - -let airdropSignature = await connection.requestAirdrop( - payer.publicKey, - web3.LAMPORTS_PER_SOL, -); - -await connection.confirmTransaction({ signature: airdropSignature }); - -let toAccount = web3.Keypair.generate(); - -// Create Simple Transaction -let transaction = new web3.Transaction(); - -// Add an instruction to execute -transaction.add( - web3.SystemProgram.transfer({ - fromPubkey: payer.publicKey, - toPubkey: toAccount.publicKey, - lamports: 1000, - }), -); - -// Send and confirm transaction -// Note: feePayer is by default the first signer, or payer, if the parameter is not set -await web3.sendAndConfirmTransaction(connection, transaction, [payer]); - -// Alternatively, manually construct the transaction -let recentBlockhash = await connection.getRecentBlockhash(); -let manualTransaction = new web3.Transaction({ - recentBlockhash: recentBlockhash.blockhash, - feePayer: payer.publicKey, -}); -manualTransaction.add( - web3.SystemProgram.transfer({ - fromPubkey: payer.publicKey, - toPubkey: toAccount.publicKey, - lamports: 1000, - }), -); - -let transactionBuffer = manualTransaction.serializeMessage(); -let signature = nacl.sign.detached(transactionBuffer, payer.secretKey); - -manualTransaction.addSignature(payer.publicKey, signature); - -let isVerifiedSignature = manualTransaction.verifySignatures(); -console.log(`The signatures were verified: ${isVerifiedSignature}`); - -// The signatures were verified: true - -let rawTransaction = manualTransaction.serialize(); - -await web3.sendAndConfirmRawTransaction(connection, rawTransaction); -``` - -### Keypair - -[Source Documentation](https://solana-labs.github.io/solana-web3.js/classes/Keypair.html) - -The keypair is used to create an account with a public key and secret key within Solana. You can either generate, generate from a seed, or create from a secret key. - -#### Example Usage - -```javascript -const { Keypair } = require("@solana/web3.js"); - -let account = Keypair.generate(); - -console.log(account.publicKey.toBase58()); -console.log(account.secretKey); - -// 2DVaHtcdTf7cm18Zm9VV8rKK4oSnjmTkKE6MiXe18Qsb -// Uint8Array(64) [ -// 152, 43, 116, 211, 207, 41, 220, 33, 193, 168, 118, -// 24, 176, 83, 206, 132, 47, 194, 2, 203, 186, 131, -// 197, 228, 156, 170, 154, 41, 56, 76, 159, 124, 18, -// 14, 247, 32, 210, 51, 102, 41, 43, 21, 12, 170, -// 166, 210, 195, 188, 60, 220, 210, 96, 136, 158, 6, -// 205, 189, 165, 112, 32, 200, 116, 164, 234 -// ] - -let seed = Uint8Array.from([ - 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, 70, - 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, -]); -let accountFromSeed = Keypair.fromSeed(seed); - -console.log(accountFromSeed.publicKey.toBase58()); -console.log(accountFromSeed.secretKey); - -// 3LDverZtSC9Duw2wyGC1C38atMG49toPNW9jtGJiw9Ar -// Uint8Array(64) [ -// 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, -// 100, 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, -// 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, 34, -// 164, 6, 12, 9, 193, 196, 30, 148, 122, 175, 11, -// 28, 243, 209, 82, 240, 184, 30, 31, 56, 223, 236, -// 227, 60, 72, 215, 47, 208, 209, 162, 59 -// ] - -let accountFromSecret = Keypair.fromSecretKey(account.secretKey); - -console.log(accountFromSecret.publicKey.toBase58()); -console.log(accountFromSecret.secretKey); - -// 2DVaHtcdTf7cm18Zm9VV8rKK4oSnjmTkKE6MiXe18Qsb -// Uint8Array(64) [ -// 152, 43, 116, 211, 207, 41, 220, 33, 193, 168, 118, -// 24, 176, 83, 206, 132, 47, 194, 2, 203, 186, 131, -// 197, 228, 156, 170, 154, 41, 56, 76, 159, 124, 18, -// 14, 247, 32, 210, 51, 102, 41, 43, 21, 12, 170, -// 166, 210, 195, 188, 60, 220, 210, 96, 136, 158, 6, -// 205, 189, 165, 112, 32, 200, 116, 164, 234 -// ] -``` - -Using `generate` generates a random Keypair for use as an account on Solana. Using `fromSeed`, you can generate a Keypair using a deterministic constructor. `fromSecret` creates a Keypair from a secret Uint8array. You can see that the publicKey for the `generate` Keypair and `fromSecret` Keypair are the same because the secret from the `generate` Keypair is used in `fromSecret`. - -**Warning**: Do not use `fromSeed` unless you are creating a seed with high entropy. Do not share your seed. Treat the seed like you would a private key. - -### PublicKey - -[Source Documentation](https://solana-labs.github.io/solana-web3.js/classes/PublicKey.html) - -PublicKey is used throughout `@solana/web3.js` in transactions, keypairs, and programs. You require publickey when listing each account in a transaction and as a general identifier on Solana. - -A PublicKey can be created with a base58 encoded string, buffer, Uint8Array, number, and an array of numbers. - -#### Example Usage - -```javascript -const { Buffer } = require("buffer"); -const web3 = require("@solana/web3.js"); -const crypto = require("crypto"); - -// Create a PublicKey with a base58 encoded string -let base58publicKey = new web3.PublicKey( - "5xot9PVkphiX2adznghwrAuxGs2zeWisNSxMW6hU6Hkj", -); -console.log(base58publicKey.toBase58()); - -// 5xot9PVkphiX2adznghwrAuxGs2zeWisNSxMW6hU6Hkj - -// Create a Program Address -let highEntropyBuffer = crypto.randomBytes(31); -let programAddressFromKey = await web3.PublicKey.createProgramAddress( - [highEntropyBuffer.slice(0, 31)], - base58publicKey, -); -console.log(`Generated Program Address: ${programAddressFromKey.toBase58()}`); - -// Generated Program Address: 3thxPEEz4EDWHNxo1LpEpsAxZryPAHyvNVXJEJWgBgwJ - -// Find Program address given a PublicKey -let validProgramAddress = await web3.PublicKey.findProgramAddress( - [Buffer.from("", "utf8")], - programAddressFromKey, -); -console.log(`Valid Program Address: ${validProgramAddress}`); - -// Valid Program Address: C14Gs3oyeXbASzwUpqSymCKpEyccfEuSe8VRar9vJQRE,253 -``` - -### SystemProgram - -[SourceDocumentation](https://solana-labs.github.io/solana-web3.js/classes/SystemProgram.html) - -The SystemProgram grants the ability to create accounts, allocate account data, assign an account to programs, work with nonce accounts, and transfer lamports. You can use the SystemInstruction class to help with decoding and reading individual instructions - -#### Example Usage - -```javascript -const web3 = require("@solana/web3.js"); - -// Airdrop SOL for paying transactions -let payer = web3.Keypair.generate(); -let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); - -let airdropSignature = await connection.requestAirdrop( - payer.publicKey, - web3.LAMPORTS_PER_SOL, -); - -await connection.confirmTransaction({ signature: airdropSignature }); - -// Allocate Account Data -let allocatedAccount = web3.Keypair.generate(); -let allocateInstruction = web3.SystemProgram.allocate({ - accountPubkey: allocatedAccount.publicKey, - space: 100, -}); -let transaction = new web3.Transaction().add(allocateInstruction); - -await web3.sendAndConfirmTransaction(connection, transaction, [ - payer, - allocatedAccount, -]); - -// Create Nonce Account -let nonceAccount = web3.Keypair.generate(); -let minimumAmountForNonceAccount = - await connection.getMinimumBalanceForRentExemption(web3.NONCE_ACCOUNT_LENGTH); -let createNonceAccountTransaction = new web3.Transaction().add( - web3.SystemProgram.createNonceAccount({ - fromPubkey: payer.publicKey, - noncePubkey: nonceAccount.publicKey, - authorizedPubkey: payer.publicKey, - lamports: minimumAmountForNonceAccount, - }), -); - -await web3.sendAndConfirmTransaction( - connection, - createNonceAccountTransaction, - [payer, nonceAccount], -); - -// Advance nonce - Used to create transactions as an account custodian -let advanceNonceTransaction = new web3.Transaction().add( - web3.SystemProgram.nonceAdvance({ - noncePubkey: nonceAccount.publicKey, - authorizedPubkey: payer.publicKey, - }), -); - -await web3.sendAndConfirmTransaction(connection, advanceNonceTransaction, [ - payer, -]); - -// Transfer lamports between accounts -let toAccount = web3.Keypair.generate(); - -let transferTransaction = new web3.Transaction().add( - web3.SystemProgram.transfer({ - fromPubkey: payer.publicKey, - toPubkey: toAccount.publicKey, - lamports: 1000, - }), -); -await web3.sendAndConfirmTransaction(connection, transferTransaction, [payer]); - -// Assign a new account to a program -let programId = web3.Keypair.generate(); -let assignedAccount = web3.Keypair.generate(); - -let assignTransaction = new web3.Transaction().add( - web3.SystemProgram.assign({ - accountPubkey: assignedAccount.publicKey, - programId: programId.publicKey, - }), -); - -await web3.sendAndConfirmTransaction(connection, assignTransaction, [ - payer, - assignedAccount, -]); -``` - -### Secp256k1Program - -[Source Documentation](https://solana-labs.github.io/solana-web3.js/classes/Secp256k1Program.html) - -The Secp256k1Program is used to verify Secp256k1 signatures, which are used by both Bitcoin and Ethereum. - -#### Example Usage - -```javascript -const { keccak_256 } = require("js-sha3"); -const web3 = require("@solana/web3.js"); -const secp256k1 = require("secp256k1"); - -// Create a Ethereum Address from secp256k1 -let secp256k1PrivateKey; -do { - secp256k1PrivateKey = web3.Keypair.generate().secretKey.slice(0, 32); -} while (!secp256k1.privateKeyVerify(secp256k1PrivateKey)); - -let secp256k1PublicKey = secp256k1 - .publicKeyCreate(secp256k1PrivateKey, false) - .slice(1); - -let ethAddress = - web3.Secp256k1Program.publicKeyToEthAddress(secp256k1PublicKey); -console.log(`Ethereum Address: 0x${ethAddress.toString("hex")}`); - -// Ethereum Address: 0xadbf43eec40694eacf36e34bb5337fba6a2aa8ee - -// Fund a keypair to create instructions -let fromPublicKey = web3.Keypair.generate(); -let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); - -let airdropSignature = await connection.requestAirdrop( - fromPublicKey.publicKey, - web3.LAMPORTS_PER_SOL, -); - -await connection.confirmTransaction({ signature: airdropSignature }); - -// Sign Message with Ethereum Key -let plaintext = Buffer.from("string address"); -let plaintextHash = Buffer.from(keccak_256.update(plaintext).digest()); -let { signature, recid: recoveryId } = secp256k1.ecdsaSign( - plaintextHash, - secp256k1PrivateKey, -); - -// Create transaction to verify the signature -let transaction = new Transaction().add( - web3.Secp256k1Program.createInstructionWithEthAddress({ - ethAddress: ethAddress.toString("hex"), - plaintext, - signature, - recoveryId, - }), -); - -// Transaction will succeed if the message is verified to be signed by the address -await web3.sendAndConfirmTransaction(connection, transaction, [fromPublicKey]); -``` - -### Message - -[Source Documentation](https://solana-labs.github.io/solana-web3.js/classes/Message.html) - -Message is used as another way to construct transactions. You can construct a message using the accounts, header, instructions, and recentBlockhash that are a part of a transaction. A [Transaction](javascript-api.md#Transaction) is a Message plus the list of required signatures required to execute the transaction. - -#### Example Usage - -```javascript -const { Buffer } = require("buffer"); -const bs58 = require("bs58"); -const web3 = require("@solana/web3.js"); - -let toPublicKey = web3.Keypair.generate().publicKey; -let fromPublicKey = web3.Keypair.generate(); - -let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); - -let airdropSignature = await connection.requestAirdrop( - fromPublicKey.publicKey, - web3.LAMPORTS_PER_SOL, -); - -await connection.confirmTransaction({ signature: airdropSignature }); - -let type = web3.SYSTEM_INSTRUCTION_LAYOUTS.Transfer; -let data = Buffer.alloc(type.layout.span); -let layoutFields = Object.assign({ instruction: type.index }); -type.layout.encode(layoutFields, data); - -let recentBlockhash = await connection.getRecentBlockhash(); - -let messageParams = { - accountKeys: [ - fromPublicKey.publicKey.toString(), - toPublicKey.toString(), - web3.SystemProgram.programId.toString(), - ], - header: { - numReadonlySignedAccounts: 0, - numReadonlyUnsignedAccounts: 1, - numRequiredSignatures: 1, - }, - instructions: [ - { - accounts: [0, 1], - data: bs58.encode(data), - programIdIndex: 2, - }, - ], - recentBlockhash, -}; - -let message = new web3.Message(messageParams); - -let transaction = web3.Transaction.populate(message, [ - fromPublicKey.publicKey.toString(), -]); - -await web3.sendAndConfirmTransaction(connection, transaction, [fromPublicKey]); -``` - -### Struct - -[SourceDocumentation](https://solana-labs.github.io/solana-web3.js/classes/Struct.html) - -The struct class is used to create Rust compatible structs in javascript. This class is only compatible with Borsh encoded Rust structs. - -#### Example Usage - -Struct in Rust: - -```rust -pub struct Fee { - pub denominator: u64, - pub numerator: u64, -} -``` - -Using web3: - -```javascript -import BN from "bn.js"; -import { Struct } from "@solana/web3.js"; - -export class Fee extends Struct { - denominator: BN; - numerator: BN; -} -``` - -### Enum - -[Source Documentation](https://solana-labs.github.io/solana-web3.js/classes/Enum.html) - -The Enum class is used to represent a Rust compatible Enum in javascript. The enum will just be a string representation if logged but can be properly encoded/decoded when used in conjunction with [Struct](javascript-api.md#Struct). This class is only compatible with Borsh encoded Rust enumerations. - -#### Example Usage - -Rust: - -```rust -pub enum AccountType { - Uninitialized, - StakePool, - ValidatorList, -} -``` - -Web3: - -```javascript -import { Enum } from "@solana/web3.js"; - -export class AccountType extends Enum {} -``` - -### NonceAccount - -[Source Documentation](https://solana-labs.github.io/solana-web3.js/classes/NonceAccount.html) - -Normally a transaction is rejected if a transaction's `recentBlockhash` field is too old. To provide for certain custodial services, Nonce Accounts are used. Transactions which use a `recentBlockhash` captured on-chain by a Nonce Account do not expire as long at the Nonce Account is not advanced. - -You can create a nonce account by first creating a normal account, then using `SystemProgram` to make the account a Nonce Account. - -#### Example Usage - -```javascript -const web3 = require("@solana/web3.js"); - -// Create connection -let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); - -// Generate accounts -let account = web3.Keypair.generate(); -let nonceAccount = web3.Keypair.generate(); - -// Fund account -let airdropSignature = await connection.requestAirdrop( - account.publicKey, - web3.LAMPORTS_PER_SOL, -); - -await connection.confirmTransaction({ signature: airdropSignature }); - -// Get Minimum amount for rent exemption -let minimumAmount = await connection.getMinimumBalanceForRentExemption( - web3.NONCE_ACCOUNT_LENGTH, -); - -// Form CreateNonceAccount transaction -let transaction = new web3.Transaction().add( - web3.SystemProgram.createNonceAccount({ - fromPubkey: account.publicKey, - noncePubkey: nonceAccount.publicKey, - authorizedPubkey: account.publicKey, - lamports: minimumAmount, - }), -); -// Create Nonce Account -await web3.sendAndConfirmTransaction(connection, transaction, [ - account, - nonceAccount, -]); - -let nonceAccountData = await connection.getNonce( - nonceAccount.publicKey, - "confirmed", -); - -console.log(nonceAccountData); -// NonceAccount { -// authorizedPubkey: PublicKey { -// _bn: -// }, -// nonce: '93zGZbhMmReyz4YHXjt2gHsvu5tjARsyukxD4xnaWaBq', -// feeCalculator: { lamportsPerSignature: 5000 } -// } - -let nonceAccountInfo = await connection.getAccountInfo( - nonceAccount.publicKey, - "confirmed", -); - -let nonceAccountFromInfo = web3.NonceAccount.fromAccountData( - nonceAccountInfo.data, -); - -console.log(nonceAccountFromInfo); -// NonceAccount { -// authorizedPubkey: PublicKey { -// _bn: -// }, -// nonce: '93zGZbhMmReyz4YHXjt2gHsvu5tjARsyukxD4xnaWaBq', -// feeCalculator: { lamportsPerSignature: 5000 } -// } -``` - -The above example shows both how to create a `NonceAccount` using `SystemProgram.createNonceAccount`, as well as how to retrieve the `NonceAccount` from accountInfo. Using the nonce, you can create transactions offline with the nonce in place of the `recentBlockhash`. - -### VoteAccount - -[SourceDocumentation](https://solana-labs.github.io/solana-web3.js/classes/VoteAccount.html) - -Vote account is an object that grants the capability of decoding vote accounts from the native vote account program on the network. - -#### Example Usage - -```javascript -const web3 = require("@solana/web3.js"); - -let voteAccountInfo = await connection.getProgramAccounts(web3.VOTE_PROGRAM_ID); -let voteAccountFromData = web3.VoteAccount.fromAccountData( - voteAccountInfo[0].account.data, -); -console.log(voteAccountFromData); -/* -VoteAccount { - nodePubkey: PublicKey { - _bn: - }, - authorizedWithdrawer: PublicKey { - _bn: - }, - commission: 10, - rootSlot: 104570885, - votes: [ - { slot: 104570886, confirmationCount: 31 }, - { slot: 104570887, confirmationCount: 30 }, - { slot: 104570888, confirmationCount: 29 }, - { slot: 104570889, confirmationCount: 28 }, - { slot: 104570890, confirmationCount: 27 }, - { slot: 104570891, confirmationCount: 26 }, - { slot: 104570892, confirmationCount: 25 }, - { slot: 104570893, confirmationCount: 24 }, - { slot: 104570894, confirmationCount: 23 }, - ... - ], - authorizedVoters: [ { epoch: 242, authorizedVoter: [PublicKey] } ], - priorVoters: [ - [Object], [Object], [Object], - [Object], [Object], [Object], - [Object], [Object], [Object], - [Object], [Object], [Object], - [Object], [Object], [Object], - [Object], [Object], [Object], - [Object], [Object], [Object], - [Object], [Object], [Object], - [Object], [Object], [Object], - [Object], [Object], [Object], - [Object], [Object] - ], - epochCredits: [ - { epoch: 179, credits: 33723163, prevCredits: 33431259 }, - { epoch: 180, credits: 34022643, prevCredits: 33723163 }, - { epoch: 181, credits: 34331103, prevCredits: 34022643 }, - { epoch: 182, credits: 34619348, prevCredits: 34331103 }, - { epoch: 183, credits: 34880375, prevCredits: 34619348 }, - { epoch: 184, credits: 35074055, prevCredits: 34880375 }, - { epoch: 185, credits: 35254965, prevCredits: 35074055 }, - { epoch: 186, credits: 35437863, prevCredits: 35254965 }, - { epoch: 187, credits: 35672671, prevCredits: 35437863 }, - { epoch: 188, credits: 35950286, prevCredits: 35672671 }, - { epoch: 189, credits: 36228439, prevCredits: 35950286 }, - ... - ], - lastTimestamp: { slot: 104570916, timestamp: 1635730116 } -} -*/ -``` - -## Staking - -### StakeProgram - -[SourceDocumentation](https://solana-labs.github.io/solana-web3.js/classes/StakeProgram.html) - -The StakeProgram facilitates staking SOL and delegating them to any validators on the network. You can use StakeProgram to create a stake account, stake some SOL, authorize accounts for withdrawal of your stake, deactivate your stake, and withdraw your funds. The StakeInstruction class is used to decode and read more instructions from transactions calling the StakeProgram - -#### Example Usage - -```javascript -const web3 = require("@solana/web3.js"); - -// Fund a key to create transactions -let fromPublicKey = web3.Keypair.generate(); -let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); - -let airdropSignature = await connection.requestAirdrop( - fromPublicKey.publicKey, - web3.LAMPORTS_PER_SOL, -); -await connection.confirmTransaction({ signature: airdropSignature }); - -// Create Account -let stakeAccount = web3.Keypair.generate(); -let authorizedAccount = web3.Keypair.generate(); -/* Note: This is the minimum amount for a stake account -- Add additional Lamports for staking - For example, we add 50 lamports as part of the stake */ -let lamportsForStakeAccount = - (await connection.getMinimumBalanceForRentExemption( - web3.StakeProgram.space, - )) + 50; - -let createAccountTransaction = web3.StakeProgram.createAccount({ - fromPubkey: fromPublicKey.publicKey, - authorized: new web3.Authorized( - authorizedAccount.publicKey, - authorizedAccount.publicKey, - ), - lamports: lamportsForStakeAccount, - lockup: new web3.Lockup(0, 0, fromPublicKey.publicKey), - stakePubkey: stakeAccount.publicKey, -}); -await web3.sendAndConfirmTransaction(connection, createAccountTransaction, [ - fromPublicKey, - stakeAccount, -]); - -// Check that stake is available -let stakeBalance = await connection.getBalance(stakeAccount.publicKey); -console.log(`Stake balance: ${stakeBalance}`); -// Stake balance: 2282930 - -// We can verify the state of our stake. This may take some time to become active -let stakeState = await connection.getStakeActivation(stakeAccount.publicKey); -console.log(`Stake state: ${stakeState.state}`); -// Stake state: inactive - -// To delegate our stake, we get the current vote accounts and choose the first -let voteAccounts = await connection.getVoteAccounts(); -let voteAccount = voteAccounts.current.concat(voteAccounts.delinquent)[0]; -let votePubkey = new web3.PublicKey(voteAccount.votePubkey); - -// We can then delegate our stake to the voteAccount -let delegateTransaction = web3.StakeProgram.delegate({ - stakePubkey: stakeAccount.publicKey, - authorizedPubkey: authorizedAccount.publicKey, - votePubkey: votePubkey, -}); -await web3.sendAndConfirmTransaction(connection, delegateTransaction, [ - fromPublicKey, - authorizedAccount, -]); - -// To withdraw our funds, we first have to deactivate the stake -let deactivateTransaction = web3.StakeProgram.deactivate({ - stakePubkey: stakeAccount.publicKey, - authorizedPubkey: authorizedAccount.publicKey, -}); -await web3.sendAndConfirmTransaction(connection, deactivateTransaction, [ - fromPublicKey, - authorizedAccount, -]); - -// Once deactivated, we can withdraw our funds -let withdrawTransaction = web3.StakeProgram.withdraw({ - stakePubkey: stakeAccount.publicKey, - authorizedPubkey: authorizedAccount.publicKey, - toPubkey: fromPublicKey.publicKey, - lamports: stakeBalance, -}); - -await web3.sendAndConfirmTransaction(connection, withdrawTransaction, [ - fromPublicKey, - authorizedAccount, -]); -``` - -### Authorized - -[Source Documentation](https://solana-labs.github.io/solana-web3.js/classes/Authorized.html) - -Authorized is an object used when creating an authorized account for staking within Solana. You can designate a `staker` and `withdrawer` separately, allowing for a different account to withdraw other than the staker. - -You can find more usage of the `Authorized` object under [`StakeProgram`](javascript-api.md#StakeProgram) - -### Lockup - -[Source Documentation](https://solana-labs.github.io/solana-web3.js/classes/Lockup.html) - -Lockup is used in conjunction with the [StakeProgram](javascript-api.md#StakeProgram) to create an account. The Lockup is used to determine how long the stake will be locked, or unable to be retrieved. If the Lockup is set to 0 for both epoch and the Unix timestamp, the lockup will be disabled for the stake account. - -#### Example Usage - -```javascript -const { - Authorized, - Keypair, - Lockup, - StakeProgram, -} = require("@solana/web3.js"); - -let account = Keypair.generate(); -let stakeAccount = Keypair.generate(); -let authorized = new Authorized(account.publicKey, account.publicKey); -let lockup = new Lockup(0, 0, account.publicKey); - -let createStakeAccountInstruction = StakeProgram.createAccount({ - fromPubkey: account.publicKey, - authorized: authorized, - lamports: 1000, - lockup: lockup, - stakePubkey: stakeAccount.publicKey, -}); -``` - -The above code creates a `createStakeAccountInstruction` to be used when creating an account with the `StakeProgram`. The Lockup is set to 0 for both the epoch and Unix timestamp, disabling lockup for the account. - -See [StakeProgram](javascript-api.md#StakeProgram) for more. diff --git a/docs/src/developing/clients/rust-api.md b/docs/src/developing/clients/rust-api.md deleted file mode 100644 index 5f74cf78df..0000000000 --- a/docs/src/developing/clients/rust-api.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: Rust API ---- - -Solana's Rust crates are [published to crates.io][crates.io] and can be found -[on docs.rs with the "solana-" prefix][docs.rs]. - -[crates.io]: https://crates.io/search?q=solana- -[docs.rs]: https://docs.rs/releases/search?query=solana- - -Some important crates: - -- [`solana-program`] — Imported by programs running on Solana, compiled - to SBF. This crate contains many fundamental data types and is re-exported from - [`solana-sdk`], which cannot be imported from a Solana program. - -- [`solana-sdk`] — The basic off-chain SDK, it re-exports - [`solana-program`] and adds more APIs on top of that. Most Solana programs - that do not run on-chain will import this. - -- [`solana-client`] — For interacting with a Solana node via the - [JSON RPC API](/api). - -- [`solana-cli-config`] — Loading and saving the Solana CLI configuration - file. - -- [`solana-clap-utils`] — Routines for setting up a CLI, using [`clap`], - as used by the main Solana CLI. Includes functions for loading all types of - signers supported by the CLI. - -[`solana-program`]: https://docs.rs/solana-program -[`solana-sdk`]: https://docs.rs/solana-sdk -[`solana-client`]: https://docs.rs/solana-client -[`solana-cli-config`]: https://docs.rs/solana-cli-config -[`solana-clap-utils`]: https://docs.rs/solana-clap-utils -[`clap`]: https://docs.rs/clap diff --git a/docs/src/developing/guides/compressed-nfts.md b/docs/src/developing/guides/compressed-nfts.md deleted file mode 100644 index 3dd613dfaf..0000000000 --- a/docs/src/developing/guides/compressed-nfts.md +++ /dev/null @@ -1,862 +0,0 @@ ---- -title: Creating Compressed NFTs with JavaScript -description: - "Compressed NFTs use the Bubblegum program from Metaplex to cheaply and - securely store NFT metadata using State Compression on Solana." -keywords: - - compression - - merkle tree - - read api - - metaplex ---- - -Compressed NFTs on Solana use the -[Bubblegum](https://docs.metaplex.com/programs/compression/) program from -Metaplex to cheaply and securely store NFT metadata using -[State Compression](../../learn/state-compression.md). - -This developer guide will use JavaScript/TypeScript to demonstrate: - -- [how to create a tree for compressed NFTs](#create-a-tree), -- [how to mint compressed NFTs into a tree](#mint-compressed-nfts), -- [how to get compressed NFT metadata from the Read API](#reading-compressed-nfts-metadata), - and -- [how to transfer compressed NFTs](#transfer-compressed-nfts) - -## Intro to Compressed NFTs - -Compressed NFTs use [State Compression](../../learn/state-compression.md) and -[merkle trees](../../learn/state-compression.md#what-is-a-merkle-tree) to -drastically reduce the storage cost for NFTs. Instead of storing an NFT's -metadata in a typical Solana account, compressed NFTs store the metadata within -the ledger. This allows compressed NFTs to still inherit the security and speed -of the Solana blockchain, while at the same time reducing the overall storage -costs. - -Even though the on-chain data storage mechanism is different than their -uncompressed counterparts, compressed NFTs still follow the exact same -[Metadata](https://docs.metaplex.com/programs/token-metadata/accounts#metadata) -schema/structure. Allowing you to define your Collection and NFT in an identical -way. - -However, the process to mint and transfer compressed NFTs is different from -uncompressed NFTs. Aside from using a different on-chain program, compressed -NFTs are minting into a merkle tree and require verification of a "proof" to -transfer. More on this below. - -### Compressed NFTs and indexers - -Since compressed NFTs store all of their metadata in the -[ledger](../../terminology.md#ledger), instead of in traditional -[accounts](../../terminology.md#account) like uncompressed NFTs, we will need to -help of indexing services to quickly fetch our compressed NFT's metadata. - -Supporting RPC providers are using the Digital Asset Standard Read API (or "Read -API" for short) to add additional RPC methods that developers can call. These -additional, NFT oriented methods, are loaded with all the information about -particular NFTs. Including support for **BOTH** compressed NFTs **AND** -uncompressed NFTs. - -:::caution Metadata is secured by the ledger and cached by indexers - -Since validators do not keep a very long history of the recent ledger data, -these indexers effectively "cache" the compressed NFT metadata passed through -the Solana ledger. Quickly serving it back on request to improve speed and user -experience of applications. - -However, since the metadata was already secured by the ledger when minting the -compressed NFT, anyone could re-index the metadata directly from the secure -ledger. Allowing for independent verification of the data, should the need or -desire arise. - -::: - -These indexing services are already available from some of the common RPC -providers, with more rolling out support in the near future. To name a few of -the RPC providers that already support the Read API: - -- Helius -- Triton -- SimpleHash - -### How to mint compressed NFTs - -The process to create or mint compressed NFTs on Solana is similar to creating a -"traditional NFT collection", with a few differences. The mint process will -happen in 3 primary steps: - -- create an NFT collection (or use an existing one) -- create a - [concurrent merkle tree](../../learn/state-compression.md#what-is-a-concurrent-merkle-tree) - (using the `@solana/spl-account-compression` SDK) -- mint compressed NFTs into your tree (to any owner's address you want) - -### How to transfer a compressed NFT - -Once your compressed NFT exists on the Solana blockchain, the process to -transfer ownership of a compressed NFT happens in a few broad steps: - -1. get the NFT "asset" information (from the indexer) -2. get the NFT's "proof" (from the indexer) -3. get the Merkle tree account (from the Solana blockchain) -4. prepare the asset proof (by parsing and formatting it) -5. build and send the transfer instruction - -The first three steps primarily involve gathering specific pieces of information -(the `proof` and the tree's canopy depth) for the NFT to be transferred. These -pieces of information are needed to correctly parse/format the `proof` to -actually be sent within the transfer instruction itself. - -## Getting started - -For this guide, we are going to make a few assumptions about the compressed NFT -collection we are going to create: - -- we are going to use TypeScript and NodeJS for this example -- we will use a single, **new** Metaplex collection - -### Project Setup - -Before we start creating our compressed NFT collection, we need to install a few -packages: - -- [`@solana/web3.js`](https://www.npmjs.com/package/@solana/web3.js) - the base - Solana JS SDK for interacting with the blockchain, including making our RPC - connection and sending transactions -- [`@solana/spl-token`](https://www.npmjs.com/package/@solana/spl-token) - used - in creating our collection and mint on-chain -- [`@solana/spl-account-compression`](https://www.npmjs.com/package/@solana/spl-account-compression) - - used to create the on-chain tree to store our compressed NFTs -- [`@metaplex-foundation/mpl-bubblegum`](https://www.npmjs.com/package/@metaplex-foundation/mpl-bubblegum) - - used to get the types and helper functions for minting and transferring - compressed NFTs on-chain -- [`@metaplex-foundation/mpl-token-metadata`](https://www.npmjs.com/package/@metaplex-foundation/mpl-token-metadata) - -used to get the types and helper functions for our NFT's metadata - - -Using your preferred package manager (e.g. npm, yarn, pnpm, etc), install these -packages into your project: - -```sh -yarn add @solana/web3.js @solana/spl-token @solana/spl-account-compression -``` - -```sh -yarn add @metaplex-foundation/mpl-bubblegum @metaplex-foundation/mpl-token-metadata -``` - -## Create a Collection - -NFTs are normally grouped together into a -[Collection](https://docs.metaplex.com/programs/token-metadata/certified-collections#collection-nfts) -using the Metaplex standard. This is true for **BOTH** traditional NFTs **AND** -compressed NFTs. The NFT Collection will store all the broad metadata for our -NFT grouping, such as the collection image and name that will appear in wallets -and explorers. - -Under the hood, an NFT collection acts similar to any other token on Solana. -More specifically, a Collection is effectively a uncompressed NFT. So we -actually create them following the same process of creating an -[SPL token](https://spl.solana.com/token): - -- create a new token "mint" -- create a associated token account (`ata`) for our token mint -- actually mint a single token -- store the collection's metadata in an Account on-chain - -Since NFT Collections having nothing special to do with -[State Compression](../../learn/state-compression.md) or -[compressed NFTs](./compressed-nfts.md), we will not cover creating one in this -guide. - -### Collection addresses - -Even though this guide does not cover creating one, we will need the many of the -various addresses for your Collection, including: - -- `collectionAuthority` - this may be your `payer` but it also might not be -- `collectionMint` - the collection's mint address -- `collectionMetadata` - the collection's metadata account -- `editionAccount` - for example, the `masterEditionAccount` created for your - collection - -## Create a tree - -One of the most important decisions to make when creating compressed NFTs is -[how to setup your tree](../../learn/state-compression.md#sizing-a-concurrent-merkle-tree). -Especially since the values used to size your tree will determine the overall -cost of creation, and **CANNOT** be changed after creation. - -:::caution - -A tree is **NOT** the same thing as a collection. A single collection can use -_any_ number of trees. In fact, this is usually recommended for larger -collections due to smaller trees having greater composability. - -Conversely, even though a tree **could** be used in multiple collections, it is -generally considered an anti-pattern and is not recommended. - -::: - -Using the helper functions provided by the -[`@solana/spl-account-compression`](https://www.npmjs.com/package/@solana/spl-account-compression) -SDK, we can create our tree in the following steps: - -- decide on our tree size -- generate a new Keypair and allocated space for the tree on-chain -- actually create the tree (making it owned by the Bubblegum program) - -### Size your tree - -Your tree size is set by 3 values, each serving a very specific purpose: - -1. `maxDepth` - used to determine how many NFTs we can have in the tree -2. `maxBufferSize` - used to determine how many updates to your tree are - possible in the same block -3. `canopyDepth` - used to store a portion of the proof on chain, and as such is - a large of cost and composability of your compressed NFT collection - -:::info - -Read more about the details about -[State Compression](../../learn/state-compression.md), including -[how to size a tree](../../learn/state-compression.md#sizing-a-concurrent-merkle-tree) -and potential composability concerns. - -::: - -Let's assume we are going to create a compressed NFT collection with 10k NFTs in -it. And since our collection is relatively small, we only need a single smaller -tree to store all the NFTs: - -```ts -// define the depth and buffer size of our tree to be created -const maxDepthSizePair: ValidDepthSizePair = { - // max=16,384 nodes (for a `maxDepth` of 14) - maxDepth: 14, - maxBufferSize: 64, -}; - -// define the canopy depth of our tree to be created -const canopyDepth = 10; -``` - -Setting a `maxDepth` of `14` will allow our tree to hold up to `16,384` -compressed NFTs, more than exceeding our `10k` collection size. - -Since only specific -[`ValidDepthSizePair`](https://solana-labs.github.io/solana-program-library/account-compression/sdk/docs/modules/index.html#ValidDepthSizePair) -pairs are allowed, simply set the `maxBufferSize` to the corresponding value -tied to your desired `maxDepth`. - -Next, setting `canopyDepth` of `10` tells our tree to store `10` of our "proof -node hashes" on-chain. Thus requiring us to always include `4` proof node values -(i.e. `maxDepth - canopyDepth`) in every compressed NFT transfer instruction. - -### Generate addresses for the tree - -When creating a new tree, we need to generate a new -[Keypair](../../terminology.md#keypair) address for the tree to have: - -```ts -const treeKeypair = Keypair.generate(); -``` - -Since our tree will be used for compressed NFTs, we will also need to derive an -Account with authority that is owned by the Bubblegum program (i.e. PDA): - -```ts -// derive the tree's authority (PDA), owned by Bubblegum -const [treeAuthority, _bump] = PublicKey.findProgramAddressSync( - [treeKeypair.publicKey.toBuffer()], - BUBBLEGUM_PROGRAM_ID, -); -``` - -### Build the tree creation instructions - -With our tree size values defined, and our addresses generated, we need to build -two related instructions: - -1. allocate enough space on-chain for our tree -2. actually create the tree, owned by the Bubblegum program - -Using the -[`createAllocTreeIx`](https://solana-labs.github.io/solana-program-library/account-compression/sdk/docs/modules/index.html#createAllocTreeIx) -helper function, we allocate enough space on-chain for our tree. - -```ts -// allocate the tree's account on chain with the `space` -const allocTreeIx = await createAllocTreeIx( - connection, - treeKeypair.publicKey, - payer.publicKey, - maxDepthSizePair, - canopyDepth, -); -``` - -Then using the -[`createCreateTreeInstruction`](https://metaplex-foundation.github.io/metaplex-program-library/docs/bubblegum/functions/createCreateTreeInstruction.html) -from the Bubblegum SDK, we actually create the tree on-chain. Making it owned by -the Bubblegum program. - -```ts -// create the instruction to actually create the tree -const createTreeIx = createCreateTreeInstruction( - { - payer: payer.publicKey, - treeCreator: payer.publicKey, - treeAuthority, - merkleTree: treeKeypair.publicKey, - compressionProgram: SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, - // NOTE: this is used for some on chain logging - logWrapper: SPL_NOOP_PROGRAM_ID, - }, - { - maxBufferSize: maxDepthSizePair.maxBufferSize, - maxDepth: maxDepthSizePair.maxDepth, - public: false, - }, - BUBBLEGUM_PROGRAM_ID, -); -``` - -### Build and send the transaction - -With our two instructions built, we can add them into a transaction and send -them to the blockchain, making sure both the `payer` and generated `treeKeypair` -sign the transaction: - -```ts -// build the transaction -const tx = new Transaction().add(allocTreeIx).add(createTreeIx); -tx.feePayer = payer.publicKey; - -// send the transaction -const txSignature = await sendAndConfirmTransaction( - connection, - tx, - // ensuring the `treeKeypair` PDA and the `payer` are BOTH signers - [treeKeypair, payer], - { - commitment: "confirmed", - skipPreflight: true, - }, -); -``` - -After a few short moments, and once the transaction is confirmed, we are ready -to start minting compressed NFTs into our tree. - -## Mint compressed NFTs - -Since compressed NFTs follow the same Metaplex -[metadata standards](https://docs.metaplex.com/programs/token-metadata/accounts#metadata) -as traditional NFTs, we can define our actual NFTs data the same way. - -The primary difference is that with compressed NFTs the metadata is actually -stored in the ledger (unlike traditional NFTs that store them in accounts). The -metadata gets "hashed" and stored in our tree, and by association, secured by -the Solana ledger. - -Allowing us to cryptographically verify that our original metadata has not -changed (unless we want it to). - -:::info - -Learn more about how State Compression uses -[concurrent merkle trees](../../learn/state-compression.md#what-is-a-concurrent-merkle-tree) -to cryptographically secure off-chain data using the Solana ledger. - -::: - -### Define our NFT's metadata - -We can define the specific metadata for the single NFT we are about to mint: - -```ts -const compressedNFTMetadata: MetadataArgs = { - name: "NFT Name", - symbol: "ANY", - // specific json metadata for each NFT - uri: "https://supersweetcollection.notarealurl/token.json", - creators: null, - editionNonce: 0, - uses: null, - collection: null, - primarySaleHappened: false, - sellerFeeBasisPoints: 0, - isMutable: false, - // these values are taken from the Bubblegum package - tokenProgramVersion: TokenProgramVersion.Original, - tokenStandard: TokenStandard.NonFungible, -}; -``` - -In this demo, the key pieces of our NFT's metadata to note are: - -- `name` - this is the actual name of our NFT that will be displayed in wallets - and on explorers. -- `uri` - this is the address for your NFTs metadata JSON file. -- `creators` - for this example, we are not storing a list of creators. If you - want your NFTs to have royalties, you will need to store actual data here. You - can checkout the Metaplex docs for more info on it. - -### Derive the Bubblegum signer - -When minting new compressed NFTs, the Bubblegum program needs a PDA to perform a -[cross-program invocation](../programming-model/calling-between-programs#cross-program-invocations) -(`cpi`) to the SPL compression program. - -:::caution - -This `bubblegumSigner` PDA is derived using a hard coded seed string of -`collection_cpi` and owned by the Bubblegum program. If this hard coded value is -not provided correctly, your compressed NFT minting will fail. - -::: - -Below, we derive this PDA using the **required** hard coded seed string of -`collection_cpi`: - -```ts -// derive a PDA (owned by Bubblegum) to act as the signer of the compressed minting -const [bubblegumSigner, _bump2] = PublicKey.findProgramAddressSync( - // `collection_cpi` is a custom prefix required by the Bubblegum program - [Buffer.from("collection_cpi", "utf8")], - BUBBLEGUM_PROGRAM_ID, -); -``` - -### Create the mint instruction - -Now we should have all the information we need to actually mint our compressed -NFT. - -Using the `createMintToCollectionV1Instruction` helper function provided in the -Bubblegum SDK, we can craft the instruction to actually mint our compressed NFT -directly into our collection. - -If you have minted traditional NFTs on Solana, this will look fairly similar. We -are creating a new instruction, giving several of the account addresses you -might expect (e.g. the `payer`, `tokenMetadataProgram`, and various collection -addresses), and then some tree specific addresses. - -The addresses to pay special attention to are: - -- `leafOwner` - this will be the owner of the compressed NFT. You can either - mint it your self (i.e. the `payer`), or airdrop to any other Solana address -- `leafDelegate` - this is the delegated authority of this specific NFT we are - about to mint. If you do not want to have a delegated authority for the NFT we - are about to mint, then this value should be set to the same address of - `leafOwner`. - -```ts -const compressedMintIx = createMintToCollectionV1Instruction( - { - payer: payer.publicKey, - - merkleTree: treeAddress, - treeAuthority, - treeDelegate: payer.publicKey, - - // set the receiver of the NFT - leafOwner: receiverAddress || payer.publicKey, - // set a delegated authority over this NFT - leafDelegate: payer.publicKey, - - // collection details - collectionAuthority: payer.publicKey, - collectionAuthorityRecordPda: BUBBLEGUM_PROGRAM_ID, - collectionMint: collectionMint, - collectionMetadata: collectionMetadata, - editionAccount: collectionMasterEditionAccount, - - // other accounts - bubblegumSigner: bubblegumSigner, - compressionProgram: SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, - logWrapper: SPL_NOOP_PROGRAM_ID, - tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID, - }, - { - metadataArgs: Object.assign(compressedNFTMetadata, { - collection: { key: collectionMint, verified: false }, - }), - }, -); -``` - -Some of the other tree specific addresses are: - -- `merkleTree` - the address of our tree we created -- `treeAuthority` - the authority of the tree -- `treeDelegate` - the delegated authority of the entire tree - -Then we also have all of our NFT collection's addresses, including the mint -address, metadata account, and edition account. These addresses are also -standard to pass in when minting uncompressed NFTs. - -#### Sign and send the transaction - -Once our compressed mint instruction has been created, we can add it to a -transaction and send it to the Solana network: - -```ts -const tx = new Transaction().add(compressedMintIx); -tx.feePayer = payer.publicKey; - -// send the transaction to the cluster -const txSignature = await sendAndConfirmTransaction(connection, tx, [payer], { - commitment: "confirmed", - skipPreflight: true, -}); -``` - -## Reading compressed NFTs metadata - -With the help of a supporting RPC provider, developers can use the Digital Asset -Standard Read API (or "Read API" for short) to fetch the metadata of NFTs. - -:::info - -The Read API supports both compressed NFTs and traditional/uncompressed NFTs. -You can use the same RPC endpoints to retrieve all the assorted information for -both types of NFTs, including auto-fetching the NFTs' JSON URI. - -::: - -### Using the Read API - -When working with the Read API and a supporting RPC provider, developers can -make `POST` requests to the RPC endpoint using your preferred method of making -such requests (e.g. `curl`, JavaScript `fetch()`, etc). - -:::warning Asset ID - -Within the Read API, digital assets (i.e. NFTs) are indexed by their `id`. This -asset `id` value differs slightly between traditional NFTs and compressed NFTs: - -- for traditional/uncompressed NFTs: this is the token's address for the actual - Account on-chain that stores the metadata for the asset. -- for compressed NFTs: this is the `id` of the compressed NFT within the tree - and is **NOT** an actual on-chain Account address. While a compressed NFT's - `assetId` resembles a traditional Solana Account address, it is not. - -::: - -### Common Read API Methods - -While the Read API supports more than these listed below, the most commonly used -methods are: - -- `getAsset` - get a specific NFT asset by its `id` -- `getAssetProof` - returns the merkle proof that is required to transfer a - compressed NFT, by its asset `id` -- `getAssetsByOwner` - get the assets owned by a specific address -- `getAssetsByGroup` - get the assets by a specific grouping (i.e. a collection) - -:::info Read API Methods, Schema, and Specification - -Explore all the additional RPC methods added by Digital Asset Standard Read API -on [Metaplex's RPC Playground](https://metaplex-read-api.surge.sh/). Here you -will also find the expected inputs and response schema for each supported RPC -method. - -::: - -### Example Read API Request - -For demonstration, below is an example request for the `getAsset` method using -the -[JavaScript Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), -which is built into modern JavaScript runtimes: - -```ts -// make a POST request to the RPC using the JavaScript `fetch` api -const response = await fetch(rpcEndpointUrl, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - jsonrpc: "2.0", - id: "rpd-op-123", - method: "getAsset", - params: { - id: "5q7qQ4FWYyj4vnFrivRBe6beo6p88X8HTkkyVPjPkQmF", - }, - }), -}); -``` - -### Example Read API Response - -With a successful response from the RPC, you should seem similar data to this: - -```ts -{ - interface: 'V1_NFT', - id: '5q7qQ4FWYyj4vnFrivRBe6beo6p88X8HTkkyVPjPkQmF', - content: [Object], - authorities: [Array], - compression: [Object], - grouping: [], - royalty: [Object], - creators: [], - ownership: [Object], - supply: [Object], - mutable: false -} -``` - -The response fields to pay special attention to are: - -- `id` - this is your asset's `id` -- `grouping` - can tell you the collection address that the NFT belongs to. The - collection address will be the `group_value`. -- `metadata` - contains the actual metadata for the NFT, including the auto - fetched JSON uri set when the NFT was minted -- `ownership` - gives you the NFT owner's address (and also if the NFT has - delegated authority to another address) -- `compression` - tells you if this NFT is actually using compression or not. - For compressed NFTs, this will also give you the tree address that is storing - the compressed NFT on chain. - -:::caution - -Some of the returned values may be empty if the NFT is **not** a compressed NFT, -such as many of the `compression` fields. This is expected. - -::: - -## Transfer compressed NFTs - -Transferring compressed NFTs is different from transferring uncompressed NFTs. -Aside from using a different on-chain program, compressed NFTs require the use -of a asset's "merkle proof" (or `proof` for short) to actually change ownership. - -:::info What is a merkle proof? - -An asset's "merkle proof" is a listing of all the "adjacent hashes" within the -tree that are required to validate a specific leaf within said tree. - -These proof hashes themselves, and the specific asset's leaf data, are hashed -together in a deterministic way to compute the "root hash". Therefore, allowing -for cryptographic validation of an asset within the merkle tree. - -**NOTE:** While each of these hash values resemble a Solana Account's -[address/public key](../../terminology.md#public-key-pubkey), they are not -addresses. - -::: - -Transferring ownership of a compressed NFT happens in 5 broad steps: - -1. get the NFT's "asset" data (from the indexer) -2. get the NFT's proof (from the indexer) -3. get the Merkle tree account (directly from the Solana blockchain) -4. prepare the asset proof -5. build and send the transfer instruction - -The first three steps primarily involve gathering specific pieces of information -(the `proof` and the tree's canopy depth) for the NFT to be transferred. These -pieces of information are needed to correctly parse/format the `proof` to -actually be sent within the transfer instruction itself. - -### Get the asset - -To perform the transfer of our compressed NFT, we will need to retrieve a few -pieces of information about the NFT. - -For starters, we will need to get some the asset's information in order to allow -the on-chain compression program to correctly perform validation and security -checks. - -We can use the `getAsset` RPC method to retrieve two important pieces of -information for the compressed NFT: the `data_hash` and `creator_hash`. - -#### Example response from the `getAsset` method - -Below is an example response from the `getAsset` method: - -```ts -compression: { - eligible: false, - compressed: true, - data_hash: 'D57LAefACeaJesajt6VPAxY4QFXhHjPyZbjq9efrt3jP', - creator_hash: '6Q7xtKPmmLihpHGVBA6u1ENE351YKoyqd3ssHACfmXbn', - asset_hash: 'F3oDH1mJ47Z7tNBHvrpN5UFf4VAeQSwTtxZeJmn7q3Fh', - tree: 'BBUkS4LZQ7mU8iZXYLVGNUjSxCYnB3x44UuPVHVXS9Fo', - seq: 3, - leaf_id: 0 -} -``` - -### Get the asset proof - -The next step in preparing your compressed NFT transfer instruction, is to get a -**valid** asset `proof` to perform the transfer. This proof is required by the -on-chain compression program to validate on-chain information. - -We can use the `getAssetProof` RPC method to retrieve two important pieces of -information: - -- `proof` - the "full proof" that is required to perform the transfer (more on - this below) -- `tree_id` - the on-chain address of the compressed NFTs tree - -:::info Full proof is returned - -The `getAssetProof` RPC method returns the complete listing of "proof hashes" -that are used to perform the compressed NFT transfer. Since this "full proof" is -returned from the RPC, we will need to remove the portion of the "full proof" -that is stored on-chain via the tree's `canopy`. - -::: - -#### Example response from the `getAssetProof` method - -Below is an example response from the `getAssetProof` method: - -```ts -{ - root: '7dy5bzgaRcUnNH2KMExwNXXNaCJnf7wQqxc2VrGXy9qr', - proof: [ - 'HdvzZ4hrPEdEarJfEzAavNJEZcCS1YU1fg2uBvQGwAAb', - ... - '3e2oBSLfSDVdUdS7jRGFKa8nreJUA9sFPEELrHaQyd4J' - ], - node_index: 131072, - leaf: 'F3oDH1mJ47Z7tNBHvrpN5UFf4VAeQSwTtxZeJmn7q3Fh', - tree_id: 'BBUkS4LZQ7mU8iZXYLVGNUjSxCYnB3x44UuPVHVXS9Fo' -} -``` - -### Get the Merkle tree account - -Since the `getAssetProof` will always return the "full proof", we will have to -reduce it down in order to remove the proof hashes that are stored on-chain in -the tree's canopy. But in order to remove the correct number of proof addresses, -we need to know the tree's `canopyDepth`. - -Once we have our compressed NFT's tree address (the `tree_id` value from -`getAssetProof`), we can use the -[`ConcurrentMerkleTreeAccount`](https://solana-labs.github.io/solana-program-library/account-compression/sdk/docs/classes/index.ConcurrentMerkleTreeAccount.html) -class, from the `@solana/spl-account-compression` SDK: - -```ts -// retrieve the merkle tree's account from the blockchain -const treeAccount = await ConcurrentMerkleTreeAccount.fromAccountAddress( - connection, - treeAddress, -); - -// extract the needed values for our transfer instruction -const treeAuthority = treeAccount.getAuthority(); -const canopyDepth = treeAccount.getCanopyDepth(); -``` - -For the transfer instruction, we will also need the current `treeAuthority` -address which we can also get via the `treeAccount`. - -### Prepare the asset proof - -With our "full proof" and `canopyDepth` values on hand, we can correctly format -the `proof` to be submitted within the transfer instruction itself. - -Since we will use the `createTransferInstruction` helper function from the -Bubblegum SDK to actually build our transfer instruction, we need to: - -- remove the proof values that are already stored on-chain in the - [tree's canopy](../../learn/state-compression.md#canopy-depth), and -- convert the remaining proof values into the valid `AccountMeta` structure that - the instruction builder function accepts - -```ts -// parse the list of proof addresses into a valid AccountMeta[] -const proof: AccountMeta[] = assetProof.proof - .slice(0, assetProof.proof.length - (!!canopyDepth ? canopyDepth : 0)) - .map((node: string) => ({ - pubkey: new PublicKey(node), - isSigner: false, - isWritable: false, - })); -``` - -In the TypeScript code example above, we are first taking a `slice` of our "full -proof", starting at the beginning of the array, and ensuring we only have -`proof.length - canopyDepth` number of proof values. This will remove the -portion of the proof that is already stored on-chain in the tree's canopy. - -Then we are structuring each of the remaining proof values as a valid -`AccountMeta`, since the proof is submitted on-chain in the form of "extra -accounts" within the transfer instruction. - -### Build the transfer instruction - -Finally, with all the required pieces of data about our tree and compressed -NFTs, and a correctly formatted proof, we are ready to actually create the -transfer instruction. - -Build your transfer instruction using the -[`createTransferInstruction`](https://metaplex-foundation.github.io/metaplex-program-library/docs/bubblegum/functions/createTransferInstruction.html) -helper function from the Bubblegum SDK: - -```ts -// create the NFT transfer instruction (via the Bubblegum package) -const transferIx = createTransferInstruction( - { - merkleTree: treeAddress, - treeAuthority, - leafOwner, - leafDelegate, - newLeafOwner, - logWrapper: SPL_NOOP_PROGRAM_ID, - compressionProgram: SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, - anchorRemainingAccounts: proof, - }, - { - root: [...new PublicKey(assetProof.root.trim()).toBytes()], - dataHash: [...new PublicKey(asset.compression.data_hash.trim()).toBytes()], - creatorHash: [ - ...new PublicKey(asset.compression.creator_hash.trim()).toBytes(), - ], - nonce: asset.compression.leaf_id, - index: asset.compression.leaf_id, - }, - BUBBLEGUM_PROGRAM_ID, -); -``` - -Aside from passing in our assorted Account addresses and the asset's proof, we -are converting the string values of our `data_hash`, `creator_hash`, `root` hash -into an array of bytes that is accepted by the `createTransferInstruction` -helper function. - -Since each of these hash values resemble and are formatted similar to -PublicKeys, we can use the -[`PublicKey`](https://solana-labs.github.io/solana-web3.js/classes/PublicKey.html) -class in web3.js to convert them into a accepted byte array format. - -#### Send the transaction - -With our transfer instructions built, we can add it into a transaction and send -it to the blockchain similar to before. Making sure either the current -`leafOwner` or the `leafDelegate` signs the transaction. - -:::note - -After each successful transfer of a compressed NFT, the `leafDelegate` should -reset to an empty value. Meaning the specific asset will not have delegated -authority to an address other than its owner. - -::: - -And once confirmed by the cluster, we will have successfully transferred a -compressed NFT. - -## Example code repository - -You can find an example code repository for this developer guide on the Solana -Developers GitHub: https://github.com/solana-developers/compressed-nfts diff --git a/docs/src/developing/intro/programs.md b/docs/src/developing/intro/programs.md deleted file mode 100644 index 161e3b47d2..0000000000 --- a/docs/src/developing/intro/programs.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: What are Solana Programs? -description: "A Solana Program, aka smart contract, is the executable code that interprets the instructions on the blockchain. There are two types: Native and on chain." ---- - -Solana Programs, often referred to as "_smart contracts_" on other blockchains, are the executable code that interprets the instructions sent inside of each transaction on the blockchain. They can be deployed directly into the core of the network as [Native Programs](#native-programs), or published by anyone as [On Chain Programs](#on-chain-programs). Programs are the core building blocks of the network and handle everything from sending tokens between wallets, to accepting votes of a DAOs, to tracking ownership of NFTs. - -Both types of programs run on top of the [Sealevel runtime](https://medium.com/solana-labs/sealevel-parallel-processing-thousands-of-smart-contracts-d814b378192), which is Solana's _parallel processing_ model that helps to enable the high transactions speeds of the blockchain. - -## Key points - -- Programs are essentially special type of [Accounts](../programming-model/accounts.md) that is marked as "_executable_" -- Programs can own other Accounts -- Programs can only _change the data_ or _debit_ accounts they own -- Any program can _read_ or _credit_ another account -- Programs are considered stateless since the primary data stored in a program account is the compiled SBF code -- Programs can be upgraded by their owner (see more on that below) - -## Types of programs - -The Solana blockchain has two types of programs: - -- Native programs -- On chain programs - -### On chain programs - -These user written programs, often referred to as "_smart contracts_" on other blockchains, are deployed directly to the blockchain for anyone to interact with and execute. Hence the name "on chain"! - -In effect, "on chain programs" are any program that is not baked directly into the Solana cluster's core code (like the native programs discussed below). - -And even though Solana Labs maintains a small subset of these on chain programs (collectively known as the [Solana Program Library](https://spl.solana.com/)), anyone can create or publish one. On chain programs can also be updated directly on the blockchain by the respective program's Account owner. - -### Native programs - -_Native programs_ are programs that are built directly into the core of the Solana blockchain. - -Similar to other "on chain" programs in Solana, native programs can be called by any other program/user. However, they can only be upgraded as part of the core blockchain and cluster updates. These native program upgrades are controlled via the releases to the [different clusters](../../cluster/overview.md). - -#### Examples of native programs include: - -- [System Program](../runtime-facilities/programs.md#system-program): Create new accounts, transfer tokens, and more -- [BPF Loader Program](../runtime-facilities/programs.md#bpf-loader): Deploys, upgrades, and executes programs on chain -- [Vote program](../runtime-facilities/programs.md#vote-program): Create and manage accounts that track validator voting state and rewards. - -## Executable - -When a Solana program is deployed onto the network, it is marked as "executable" by the [BPF Loader Program](../runtime-facilities/programs.md#bpf-loader). This allows the Solana runtime to efficiently and properly execute the compiled program code. - -## Upgradable - -Unlike other blockchains, Solana programs can be upgraded after they are deployed to the network. - -Native programs can only be upgraded as part of cluster updates when new software releases are made. - -On chain programs can be upgraded by the account that is marked as the "_Upgrade Authority_", which is usually the Solana account/address that deployed the program to begin with. diff --git a/docs/src/developing/intro/rent.md b/docs/src/developing/intro/rent.md deleted file mode 100644 index 2938e7044b..0000000000 --- a/docs/src/developing/intro/rent.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: What is rent? -description: "Rent: the small fee Solana accounts incur to store data on the blockchain. Accounts with >2 years of rent are rent exempt and do not pay the periodic fee." ---- - -The fee for every Solana Account to store data on the blockchain is called "_rent_". This _time and space_ based fee is required to keep an account, and therefore its data, alive on the blockchain since [clusters](../../cluster/overview.md) must actively maintain this data. - -All Solana Accounts (and therefore Programs) are required to maintain a high enough LAMPORT balance to become [rent exempt](#rent-exempt) and remain on the Solana blockchain. - -When an Account no longer has enough LAMPORTS to pay its rent, it will be removed from the network in a process known as [Garbage Collection](#garbage-collection). - -> **Note:** Rent is different from [transactions fees](../../transaction_fees.md). Rent is paid (or held in an Account) to keep data stored on the Solana blockchain. Whereas transaction fees are paid to process [instructions](../developing/../programming-model/transactions.md#instructions) on the network. - -### Rent rate - -The Solana rent rate is set on a network wide basis, primarily based on the set LAMPORTS _per_ byte _per_ year. - -Currently, the rent rate is a static amount and stored in the [Rent sysvar](../runtime-facilities/sysvars.md#rent). - -## Rent exempt - -Accounts that maintain a minimum LAMPORT balance greater than 2 years worth of rent payments are considered "_rent exempt_" and will not incur a rent collection. - -> At the time of writing this, new Accounts and Programs **are required** to be initialized with enough LAMPORTS to become rent-exempt. The RPC endpoints have the ability to calculate this [estimated rent exempt balance](../../api/http#getminimumbalanceforrentexemption) and is recommended to be used. - -Every time an account's balance is reduced, a check is performed to see if the account is still rent exempt. Transactions that would cause an account's balance to drop below the rent exempt threshold will fail. - -## Garbage collection - -Accounts that do not maintain their rent exempt status, or have a balance high enough to pay rent, are removed from the network in a process known as _garbage collection_. This process is done to help reduce the network wide storage of no longer used/maintained data. - -You can learn more about [garbage collection here](../../implemented-proposals/persistent-account-storage.md#garbage-collection) in this implemented proposal. - -## Learn more about Rent - -You can learn more about Solana Rent with the following articles and documentation: - -- [Implemented Proposals - Rent](../../implemented-proposals/rent.md) -- [Implemented Proposals - Account Storage](../../implemented-proposals/persistent-account-storage.md) diff --git a/docs/src/developing/intro/transaction_fees.md b/docs/src/developing/intro/transaction_fees.md deleted file mode 100644 index 1013665bd9..0000000000 --- a/docs/src/developing/intro/transaction_fees.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Transaction Fees -description: "Transaction fees are the small fees paid to process instructions on the network. These fees are based on computation and an optional prioritization fee." -keywords: - - instruction fee - - processing fee - - storage fee - - low fee blockchain - - gas - - gwei - - cheap network - - affordable blockchain ---- - -The small fees paid to process [instructions](./../../terminology.md#instruction) on the Solana blockchain are known as "_transaction fees_". - -As each transaction (which contains one or more instructions) is sent through the network, it gets processed by the current leader validation-client. Once confirmed as a global state transaction, this _transaction fee_ is paid to the network to help support the economic design of the Solana blockchain. - -> NOTE: Transactions fees are different from the blockchain's data storage fee called [rent](./rent.md) - -### Transaction Fee Calculation - -Currently, the amount of resources consumed by a transaction do not impact fees in any way. This is because the runtime imposes a small cap on the amount of resources that transaction instructions can use, not to mention that the size of transactions is limited as well. So right now, transaction fees are solely determined by the number of signatures that need to be verified in a transaction. The only limit on the number of signatures in a transaction is the max size of transaction itself. Each signature (64 bytes) in a transaction (max 1232 bytes) must reference a unique public key (32 bytes) so a single transaction could contain as many as 12 signatures (not sure why you would do that). The fee per transaction signature can be fetched with the `solana` cli: - -```bash -$ solana fees -Blockhash: 8eULQbYYp67o5tGF2gxACnBCKAE39TetbYYMGTx3iBFc -Lamports per signature: 5000 -Last valid block height: 94236543 -``` - -The `solana` cli `fees` subcommand calls the `getFees` RPC API method to retrieve the above output information, so your application can call that method directly as well: - -```bash -$ curl http://api.mainnet-beta.solana.com -H "Content-Type: application/json" -d ' - {"jsonrpc":"2.0","id":1, "method":"getFees"} -' - -# RESULT (lastValidSlot removed since it's inaccurate) -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 106818885 - }, - "value": { - "blockhash": "78e3YBCMXJBiPD1HpyVtVfFzZFPG6nUycnQcyNMSUQzB", - "feeCalculator": { - "lamportsPerSignature": 5000 - }, - "lastValidBlockHeight": 96137823 - } - }, - "id": 1 -} -``` - -### Fee Determinism - -It's important to keep in mind that fee rates (such as `lamports_per_signature`) are subject to change from block to block (though that hasn't happened in the full history of the `mainnet-beta` cluster). Despite the fact that fees can fluctuate, fees for a transaction can still be calculated deterministically when creating (and before signing) a transaction. This determinism comes from the fact that fees are applied using the rates from the block whose blockhash matches the `recent_blockhash` field in a transaction. Blockhashes can only be referenced by a transaction for a few minutes before they expire. - -Transactions with expired blockhashes will be ignored and dropped by the cluster, so it's important to understand how expiration actually works. Before transactions are added to a block and during block validation, [each transaction's recent blockhash is checked](https://github.com/solana-labs/solana/blob/647aa926673e3df4443d8b3d9e3f759e8ca2c44b/runtime/src/bank.rs#L3482) to ensure it hasn't expired yet. The max age of a transaction's blockhash is only 150 blocks. This means that if no slots are skipped in between, the blockhash for block 100 would be usable by transactions processed in blocks 101 to 252, inclusive (during block 101 the age of block 100 is "0" and during block 252 its age is "150"). However, it's important to remember that slots may be skipped and that age checks use "block height" _not_ "slot height". Since slots are skipped occasionally, the actual age of a blockhash can be a bit longer than 150 slots. At the time of writing, slot times are about 500ms and skip rate is about 5% so the expected lifetime of a transaction which uses the most recent blockhash is about 1min 19s. - -### Fee Collection - -Transactions are required to have at least one account which has signed the transaction and is writable. Writable signer accounts are serialized first in the list of transaction accounts and the first of these accounts is always used as the "fee payer". - -Before any transaction instructions are processed, the fee payer account balance will be deducted to pay for transaction fees. If the fee payer balance is not sufficient to cover transaction fees, the transaction will be dropped by the cluster. If the balance was sufficient, the fees will be deducted whether the transaction is processed successfully or not. In fact, if any of the transaction instructions return an error or violate runtime restrictions, all account changes _except_ the transaction fee deduction will be rolled back. - -### Fee Distribution - -Transaction fees are partially burned and the remaining fees are collected by the validator that produced the block that the corresponding transactions were included in. The transaction fee burn rate was initialized as 50% when inflation rewards were enabled at the beginning of 2021 and has not changed so far. These fees incentivize a validator to process as many transactions as possible during its slots in the leader schedule. Collected fees are deposited in the validator's account (listed in the leader schedule for the current slot) after processing all of the transactions included in a block. diff --git a/docs/src/developing/lookup-tables.md b/docs/src/developing/lookup-tables.md deleted file mode 100644 index 1d02c899fa..0000000000 --- a/docs/src/developing/lookup-tables.md +++ /dev/null @@ -1,148 +0,0 @@ ---- -title: Address Lookup Tables -description: "" ---- - -Address Lookup Tables, commonly referred to as "_lookup tables_" or "_ALTs_" for short, allow developers to create a collection of related addresses to efficiently load more addresses in a single transaction. - -Since each transaction on the Solana blockchain requires a listing of every address that is interacted with as part of the transaction, this listing would effectively be capped at 32 addresses per transaction. With the help of [Address Lookup Tables](./lookup-tables.md), a transaction would now be able to raise that limit to 256 addresses per transaction. - -## Compressing on chain addresses - -After all the desired addresses have been stored on chain in an Address Lookup Table, each address can be referenced inside a transaction by its 1-byte index within the table (instead of their full 32-byte address). This lookup method effectively "_compresses_" a 32-byte address into a 1-byte index value. - -This "_compression_" enables storing up to 256 addresses in a single lookup table for use inside any given transaction. - -## Versioned Transactions - -To utilize an Address Lookup Table inside a transaction, developers must use v0 transactions that were introduced with the new [Versioned Transaction format](./versioned-transactions.md). - -## How to create an address lookup table - -Creating a new lookup table with the `@solana/web3.js` library is similar to the older `legacy` transactions, but with some differences. - -Using the `@solana/web3.js` library, you can use the [`createLookupTable`](https://solana-labs.github.io/solana-web3.js/classes/AddressLookupTableProgram.html#createLookupTable) function to construct the instruction needed to create a new lookup table, as well as determine its address: - -```js -const web3 = require("@solana/web3.js"); - -// connect to a cluster and get the current `slot` -const connection = new web3.Connection(web3.clusterApiUrl("devnet")); -const slot = await connection.getSlot(); - -// Assumption: -// `payer` is a valid `Keypair` with enough SOL to pay for the execution - -const [lookupTableInst, lookupTableAddress] = - web3.AddressLookupTableProgram.createLookupTable({ - authority: payer.publicKey, - payer: payer.publicKey, - recentSlot: slot, - }); - -console.log("lookup table address:", lookupTableAddress.toBase58()); - -// To create the Address Lookup Table on chain: -// send the `lookupTableInst` instruction in a transaction -``` - -> NOTE: -> Address lookup tables can be **created** with either a `v0` transaction or a `legacy` transaction. But the Solana runtime can only retrieve and handle the additional addresses within a lookup table while using [v0 Versioned Transactions](./versioned-transactions.md#current-transaction-versions). - -## Add addresses to a lookup table - -Adding addresses to a lookup table is known as "_extending_". Using the `@solana/web3.js` library, you can create a new _extend_ instruction using the [`extendLookupTable`](https://solana-labs.github.io/solana-web3.js/classes/AddressLookupTableProgram.html#extendLookupTable) method: - -```js -// add addresses to the `lookupTableAddress` table via an `extend` instruction -const extendInstruction = web3.AddressLookupTableProgram.extendLookupTable({ - payer: payer.publicKey, - authority: payer.publicKey, - lookupTable: lookupTableAddress, - addresses: [ - payer.publicKey, - web3.SystemProgram.programId, - // list more `publicKey` addresses here - ], -}); - -// Send this `extendInstruction` in a transaction to the cluster -// to insert the listing of `addresses` into your lookup table with address `lookupTableAddress` -``` - -> NOTE: -> Due to the same memory limits of `legacy` transactions, any transaction used to _extend_ an Address Lookup Table is also limited in how many addresses can be added at a time. Because of this, you will need to use multiple transactions to _extend_ any table with more addresses (~20) that can fit within a single transaction's memory limits. - -Once these addresses have been inserted into the table, and stored on chain, you will be able to utilize the Address Lookup Table in future transactions. Enabling up to 256 addresses in those future transactions. - -## Fetch an Address Lookup Table - -Similar to requesting another account (or PDA) from the cluster, you can fetch a complete Address Lookup Table with the [`getAddressLookupTable`](https://solana-labs.github.io/solana-web3.js/classes/Connection.html#getAddressLookupTable) method: - -```js -// define the `PublicKey` of the lookup table to fetch -const lookupTableAddress = new web3.PublicKey(""); - -// get the table from the cluster -const lookupTableAccount = (await connection.getAddressLookupTable(lookupTableAddress)).value; - -// `lookupTableAccount` will now be a `AddressLookupTableAccount` object - -console.log("Table address from cluster:", lookupTableAccount.key.toBase58()); -``` - -Our `lookupTableAccount` variable will now be a `AddressLookupTableAccount` object which we can parse to read the listing of all the addresses stored on chain in the lookup table: - -```js -// loop through and parse all the addresses stored in the table -for (let i = 0; i < lookupTableAccount.state.addresses.length; i++) { - const address = lookupTableAccount.state.addresses[i]; - console.log(i, address.toBase58()); -} -``` - -## How to use an address lookup table in a transaction - -After you have created your lookup table, and stored your needed address on chain (via extending the lookup table), you can create a `v0` transaction to utilize the on chain lookup capabilities. - -Just like older `legacy` transactions, you can create all the [instructions](./../terminology.md#instruction) your transaction will execute on chain. You can then provide an array of these instructions to the [Message](./../terminology.md#message) used in the `v0 transaction. - -> NOTE: -> The instructions used inside a `v0` transaction can be constructed using the same methods and functions used to create the instructions in the past. There is no required change to the instructions used involving an Address Lookup Table. - -```js -// Assumptions: -// - `arrayOfInstructions` has been created as an `array` of `TransactionInstruction` -// - we are using the `lookupTableAccount` obtained above - -// construct a v0 compatible transaction `Message` -const messageV0 = new web3.TransactionMessage({ - payerKey: payer.publicKey, - recentBlockhash: blockhash, - instructions: arrayOfInstructions, // note this is an array of instructions -}).compileToV0Message([lookupTableAccount]); - -// create a v0 transaction from the v0 message -const transactionV0 = new web3.VersionedTransaction(messageV0); - -// sign the v0 transaction using the file system wallet we created named `payer` -transactionV0.sign([payer]); - -// send and confirm the transaction -// (NOTE: There is NOT an array of Signers here; see the note below...) -const txid = await web3.sendAndConfirmTransaction(connection, transactionV0); - -console.log( - `Transaction: https://explorer.solana.com/tx/${txid}?cluster=devnet`, -); -``` - -> NOTE: -> When sending a `VersionedTransaction` to the cluster, it must be signed BEFORE calling the -> `sendAndConfirmTransaction` method. If you pass an array of `Signer` -> (like with `legacy` transactions) the method will trigger an error! - -## More Resources - -- Read the [proposal](./../proposals/versioned-transactions.md) for Address Lookup Tables and Versioned transactions -- [Example Rust program using Address Lookup Tables](https://github.com/TeamRaccoons/address-lookup-table-multi-swap) diff --git a/docs/src/developing/on-chain-programs/debugging.md b/docs/src/developing/on-chain-programs/debugging.md deleted file mode 100644 index fdbb1aebaa..0000000000 --- a/docs/src/developing/on-chain-programs/debugging.md +++ /dev/null @@ -1,266 +0,0 @@ ---- -title: "Debugging Programs" ---- - -Solana programs run on-chain, so debugging them in the wild can be challenging. -To make debugging programs easier, developers can write unit tests that directly -test their program's execution via the Solana runtime, or run a local cluster -that will allow RPC clients to interact with their program. - -## Running unit tests - -- [Testing with Rust](developing-rust.md#how-to-test) -- [Testing with C](developing-c.md#how-to-test) - -## Logging - -During program execution both the runtime and the program log status and error -messages. - -For information about how to log from a program see the language specific -documentation: - -- [Logging from a Rust program](developing-rust.md#logging) -- [Logging from a C program](developing-c.md#logging) - -When running a local cluster the logs are written to stdout as long as they are -enabled via the `RUST_LOG` log mask. From the perspective of program -development it is helpful to focus on just the runtime and program logs and not -the rest of the cluster logs. To focus in on program specific information the -following log mask is recommended: - -`export RUST_LOG=solana_runtime::system_instruction_processor=trace,solana_runtime::message_processor=info,solana_bpf_loader=debug,solana_rbpf=debug` - -Log messages coming directly from the program (not the runtime) will be -displayed in the form: - -`Program log: ` - -## Error Handling - -The amount of information that can be communicated via a transaction error is -limited but there are many points of possible failures. The following are -possible failure points and information about what errors to expect and where to -get more information: - -- The SBF loader may fail to parse the program, this should not happen since the - loader has already _finalized_ the program's account data. - - `InstructionError::InvalidAccountData` will be returned as part of the - transaction error. -- The SBF loader may fail to setup the program's execution environment - - `InstructionError::Custom(0x0b9f_0001)` will be returned as part of the - transaction error. "0x0b9f_0001" is the hexadecimal representation of - [`VirtualMachineCreationFailed`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/programs/bpf_loader/src/lib.rs#L44). -- The SBF loader may have detected a fatal error during program executions - (things like panics, memory violations, system call errors, etc...) - - `InstructionError::Custom(0x0b9f_0002)` will be returned as part of the - transaction error. "0x0b9f_0002" is the hexadecimal representation of - [`VirtualMachineFailedToRunProgram`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/programs/bpf_loader/src/lib.rs#L46). -- The program itself may return an error - - `InstructionError::Custom()` will be returned. The - "user defined value" must not conflict with any of the [builtin runtime - program - errors](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/sdk/program/src/program_error.rs#L87). - Programs typically use enumeration types to define error codes starting at - zero so they won't conflict. - -In the case of `VirtualMachineFailedToRunProgram` errors, more information about -the specifics of what failed are written to the [program's execution -logs](debugging.md#logging). - -For example, an access violation involving the stack will look something like -this: - -`SBF program 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM failed: out of bounds memory store (insn #615), addr 0x200001e38/8` - -## Monitoring Compute Budget Consumption - -The program can log the remaining number of compute units it will be allowed -before program execution is halted. Programs can use these logs to wrap -operations they wish to profile. - -- [Log the remaining compute units from a Rust - program](developing-rust.md#compute-budget) -- [Log the remaining compute units from a C - program](developing-c.md#compute-budget) - -See [compute budget](developing/programming-model/runtime.md#compute-budget) -for more information. - -## ELF Dump - -The SBF shared object internals can be dumped to a text file to gain more -insight into a program's composition and what it may be doing at runtime. - -- [Create a dump file of a Rust program](developing-rust.md#elf-dump) -- [Create a dump file of a C program](developing-c.md#elf-dump) - -## Instruction Tracing - -During execution the runtime SBF interpreter can be configured to log a trace -message for each SBF instruction executed. This can be very helpful for things -like pin-pointing the runtime context leading up to a memory access violation. - -The trace logs together with the [ELF dump](#elf-dump) can provide a lot of -insight (though the traces produce a lot of information). - -To turn on SBF interpreter trace messages in a local cluster configure the -`solana_rbpf` level in `RUST_LOG` to `trace`. For example: - -`export RUST_LOG=solana_rbpf=trace` - - -## Source level debugging - -Source level debugging of on-chain programs written in Rust or C can -be done using the `program run` subcommand of `solana-ledger-tool`, -and lldb, distributed with Solana Rust and Clang compiler binary -package platform-tools. - -The `solana-ledger-tool program run` subcommand loads a compiled -on-chain program, executes it in RBPF virtual machine and runs a gdb -server that accepts incoming connections from LLDB or GDB. Once lldb -is connected to `solana-ledger-tool` gdbserver, it can control -execution of an on-chain program. Run `solana-ledger-tool program run ---help` for an example of specifying input data for parameters of the -program entrypoint function. - -To compile a program for debugging use cargo-build-sbf build utility -with the command line option `--debug`. The utility will generate two -loadable files, one a usual loadable module with the extension `.so`, -and another the same loadable module but containing Dwarf debug -information, a file with extension `.debug`. - -To execute a program in debugger, run `solana-ledger-tool program run` -with `-e debugger` command line option. For example, a crate named -'helloworld' is compiled and an executable program is built in -`target/deploy` directory. There should be three files in that -directory -- helloworld-keypair.json -- a keypair for deploying the program, -- helloworld.debug -- a binary file containing debug information, -- helloworld.so -- an executable file loadable into the virtual machine. -The command line for running `solana-ledger-tool` would be something like this -``` -solana-ledger-tool program run -l test-ledger -e debugger target/deploy/helloworld.so -``` -Note that `solana-ledger-tool` always loads a ledger database. Most -on-chain programs interact with a ledger in some manner. Even if for -debugging purpose a ledger is not needed, it has to be provided to -`solana-ledger-tool`. A minimal ledger database can be created by -running `solana-test-validator`, which creates a ledger in -`test-ledger` subdirectory. - -In debugger mode `solana-ledger-tool program run` loads an `.so` file and -starts listening for an incoming connection from a debugger -``` -Waiting for a Debugger connection on "127.0.0.1:9001"... -``` - -To connect to `solana-ledger-tool` and execute the program, run lldb. For -debugging rust programs it may be beneficial to run solana-lldb -wrapper to lldb, i.e. at a new shell prompt (other than the one used -to start `solana-ledger-tool`) run the command - -``` -solana-lldb -``` - -This script is installed in platform-tools path. If that path is not -added to `PATH` environment variable, it may be necessary to specify -the full path, e.g. -``` -~/.cache/solana/v1.35/platform-tools/llvm/bin/solana-lldb -``` -After starting the debugger, load the .debug file by entering the -following command at the debugger prompt -``` -(lldb) file target/deploy/helloworld.debug -``` -If the debugger finds the file, it will print something like this -``` -Current executable set to '/path/helloworld.debug' (bpf). -``` - -Now, connect to the gdb server that `solana-ledger-tool` implements, and -debug the program as usual. Enter the following command at lldb prompt -``` -(lldb) gdb-remote 127.0.0.1:9001 -``` -If the debugger and the gdb server establish a connection, the -execution of the program will be stopped at the entrypoint function, -and lldb should print several lines of the source code around the -entrypoint function signature. From this point on, normal lldb -commands can be used to control execution of the program being -debugged. - - -### Debugging in an IDE - -To debug on-chain programs in Visual Studio IDE, install the CodeLLDB -extension. Open CodeLLDB Extension Settings. In -Advanced settings change the value of `Lldb: Library` field to the -path of `liblldb.so` (or liblldb.dylib on macOS). For example on Linux a -possible path to Solana customized lldb can be -`/home//.cache/solana/v1.33/platform-tools/llvm/lib/liblldb.so.` -where `` is your Linux system username. This can also be added -directly to `~/.config/Code/User/settings.json` file, e.g. -``` -{ - "lldb.library": "/home//.cache/solana/v1.35/platform-tools/llvm/lib/liblldb.so" -} -``` - -In `.vscode` subdirectory of your on-chain project, create two files - -First file is `tasks.json` with the following content -``` -{ - "version": "2.0.0", - "tasks": [ - { - "label": "build", - "type": "shell", - "command": "cargo build-sbf --debug", - "problemMatcher": [], - "group": { - "kind": "build", - "isDefault": true - } - }, - { - "label": "solana-debugger", - "type": "shell", - "command": "solana-ledger-tool program run -l test-ledger -e debugger ${workspaceFolder}/target/deploy/helloworld.so" - } - ] -} -``` -The first task is to build the on-chain program using cargo-build-sbf -utility. The second task is to run `solana-ledger-tool program run` in debugger mode. - -Another file is `launch.json` with the following content -``` -{ - "version": "0.2.0", - "configurations": [ - { - "type": "lldb", - "request": "custom", - "name": "Debug", - "targetCreateCommands": ["target create ${workspaceFolder}/target/deploy/helloworld.debug"], - "processCreateCommands": ["gdb-remote 127.0.0.1:9001"] - } - ] -} -``` -This file specifies how to run debugger and to connect it to the gdb -server implemented by `solana-ledger-tool`. - -To start debugging a program, first build it by running the build -task. The next step is to run `solana-debugger` task. The tasks specified in -`tasks.json` file are started from `Terminal >> Run Task...` menu of -VSCode. When `solana-ledger-tool` is running and listening from incoming -connections, it's time to start the debugger. Launch it from VSCode -`Run and Debug` menu. If everything is set up correctly, VSCode will -start a debugging session and the program execution should stop on -the entrance into the `entrypoint` function. diff --git a/docs/src/developing/on-chain-programs/deploying.md b/docs/src/developing/on-chain-programs/deploying.md deleted file mode 100644 index 2f0d095444..0000000000 --- a/docs/src/developing/on-chain-programs/deploying.md +++ /dev/null @@ -1,143 +0,0 @@ ---- -title: "Deploying Programs" -description: "Deploying on-chain programs can be done using the Solana CLI using the Upgradable BPF loader to upload the compiled byte-code to the Solana blockchain." ---- - -Solana on-chain programs (otherwise known as "smart contracts") are stored in "executable" accounts on Solana. These accounts are identical to any other account but with the exception of: - -- having the "executable" flag enabled, and -- the owner being assigned to a BPF loader - -Besides those exceptions, they are governed by the same runtime rules as non-executable accounts, hold SOL tokens for rent fees, and store a data buffer which is managed by the BPF loader program. The latest BPF loader is called the "Upgradeable BPF Loader". - -## Overview of the Upgradeable BPF Loader - -### State accounts - -The Upgradeable BPF loader program supports three different types of state accounts: - -1. [Program account](https://github.com/solana-labs/solana/blob/master/sdk/program/src/bpf_loader_upgradeable.rs#L34): This is the main account of an on-chain program and its address is commonly referred to as a "program id." Program id's are what transaction instructions reference in order to invoke a program. Program accounts are immutable once deployed, so you can think of them as a proxy account to the byte-code and state stored in other accounts. -2. [Program data account](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/bpf_loader_upgradeable.rs#L39): This account is what stores the executable byte-code of an on-chain program. When a program is upgraded, this account's data is updated with new byte-code. In addition to byte-code, program data accounts are also responsible for storing the slot when it was last modified and the address of the sole account authorized to modify the account (this address can be cleared to make a program immutable). -3. [Buffer accounts](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/bpf_loader_upgradeable.rs#L27): These accounts temporarily store byte-code while a program is being actively deployed through a series of transactions. They also each store the address of the sole account which is authorized to do writes. - -### Instructions - -The state accounts listed above can only be modified with one of the following instructions supported by the Upgradeable BPF Loader program: - -1. [Initialize buffer](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L21): Creates a buffer account and stores an authority address which is allowed to modify the buffer. -2. [Write](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L28): Writes byte-code at a specified byte offset inside a buffer account. Writes are processed in small chunks due to a limitation of Solana transactions having a maximum serialized size of 1232 bytes. -3. [Deploy](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L77): Creates both a program account and a program data account. It fills the program data account by copying the byte-code stored in a buffer account. If the byte-code is valid, the program account will be set as executable, allowing it to be invoked. If the byte-code is invalid, the instruction will fail and all changes are reverted. -4. [Upgrade](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L102): Fills an existing program data account by copying executable byte-code from a buffer account. Similar to the deploy instruction, it will only succeed if the byte-code is valid. -5. [Set authority](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L114): Updates the authority of a program data or buffer account if the account's current authority has signed the transaction being processed. If the authority is deleted without replacement, it can never be set to a new address and the account can never be closed. -6. [Close](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L127): Clears the data of a program data account or buffer account and reclaims the SOL used for the rent exemption deposit. - -## How `solana program deploy` works - -Deploying a program on Solana requires hundreds, if not thousands of transactions, due to the max size limit of 1232 bytes for Solana transactions. The Solana CLI takes care of this rapid firing of transactions with the `solana program deploy` subcommand. The process can be broken down into the following 3 phases: - -1. [Buffer initialization](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2113): First, the CLI sends a transaction which [creates a buffer account](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1903) large enough for the byte-code being deployed. It also invokes the [initialize buffer instruction](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L320) to set the buffer authority to restrict writes to the deployer's chosen address. -2. [Buffer writes](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2129): Once the buffer account is initialized, the CLI [breaks up the program byte-code](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1940) into ~1KB chunks and [sends transactions at a rate of 100 transactions per second](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/client/src/tpu_client.rs#L133) to write each chunk with [the write buffer instruction](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L334). These transactions are sent directly to the current leader's transaction processing (TPU) port and are processed in parallel with each other. Once all transactions have been sent, the CLI [polls the RPC API with batches of transaction signatures](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/client/src/tpu_client.rs#L216) to ensure that every write was successful and confirmed. -3. [Finalization](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1807): Once writes are completed, the CLI [sends a final transaction](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2150) to either [deploy a new program](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L362) or [upgrade an existing program](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L513). In either case, the byte-code written to the buffer account will be copied into a program data account and verified. - -## Reclaim rent from program accounts - -The storage of data on the Solana blockchain requires the payment of [rent](./../intro/rent.md), including for the byte-code for on-chain programs. Therefore as you deploy more or larger programs, the amount of rent paid to remain rent-exempt will also become larger. - -Using the current rent cost model configuration, a rent-exempt account requires a deposit of ~0.7 SOL per 100KB stored. These costs can have an outsized impact on developers who deploy their own programs since [program accounts](./../programming-model/accounts.md#executable) are among the largest we typically see on Solana. - -#### Example of how much data is used for programs - -As a data point of the number of accounts and potential data stored on-chain, below is the distribution of the largest accounts (at least 100KB) at slot `103,089,804` on `mainnet-beta` by assigned on-chain program: - -1. **Serum Dex v3**: 1798 accounts -2. **Metaplex Candy Machine**: 1089 accounts -3. **Serum Dex v2**: 864 accounts -4. **Upgradeable BPF Program Loader**: 824 accounts -5. **BPF Program Loader v2**: 191 accounts -6. **BPF Program Loader v1**: 150 accounts - -> _Note: this data was pulled with a modified `solana-ledger-tool` built from this branch: [https://github.com/jstarry/solana/tree/large-account-stats](https://github.com/jstarry/solana/tree/large-account-stats)_ - -### Reclaiming buffer accounts - -Buffer accounts are used by the Upgradeable BPF loader to temporarily store byte-code that is in the process of being deployed on-chain. This temporary buffer is required when upgrading programs because the currently deployed program's byte-code cannot be affected by an in-progress upgrade. - -Unfortunately, deploys fail occasionally and instead of reusing the buffer account, developers might retry their deployment with a new buffer and not realize that they stored a good chunk of SOL in a forgotten buffer account from an earlier deploy. - -> As of slot `103,089,804` on `mainnet-beta` there are 276 abandoned buffer accounts that could be reclaimed! - -Developers can check if they own any abandoned buffer accounts by using the Solana CLI: - -```bash -solana program show --buffers --keypair ~/.config/solana/MY_KEYPAIR.json - -Buffer Address | Authority | Balance -9vXW2c3qo6DrLHa1Pkya4Mw2BWZSRYs9aoyoP3g85wCA | 2nr1bHFT86W9tGnyvmYW4vcHKsQB3sVQfnddasz4kExM | 3.41076888 SOL -``` - -And they can close those buffers to reclaim the SOL balance with the following command: - -```bash -solana program close --buffers --keypair ~/.config/solana/MY_KEYPAIR.json -``` - -#### Fetch the owners of buffer accounts via RPC API - -The owners of all abandoned program deploy buffer accounts can be fetched via the RPC API: - -```bash -curl http://api.mainnet-beta.solana.com -H "Content-Type: application/json" \ ---data-binary @- << EOF | jq --raw-output '.result | .[] | .account.data[0]' -{ - "jsonrpc":"2.0", "id":1, "method":"getProgramAccounts", - "params":[ - "BPFLoaderUpgradeab1e11111111111111111111111", - { - "dataSlice": {"offset": 5, "length": 32}, - "filters": [{"memcmp": {"offset": 0, "bytes": "2UzHM"}}], - "encoding": "base64" - } - ] -} -EOF -``` - -After re-encoding the base64 encoded keys into base58 and grouping by key, we see some accounts have over 10 buffer accounts they could close, yikes! - -```bash -'BE3G2F5jKygsSNbPFKHHTxvKpuFXSumASeGweLcei6G3' => 10 buffer accounts -'EsQ179Q8ESroBnnmTDmWEV4rZLkRc3yck32PqMxypE5z' => 10 buffer accounts -'6KXtB89kAgzW7ApFzqhBg5tgnVinzP4NSXVqMAWnXcHs' => 12 buffer accounts -'FinVobfi4tbdMdfN9jhzUuDVqGXfcFnRGX57xHcTWLfW' => 15 buffer accounts -'TESAinbTL2eBLkWqyGA82y1RS6kArHvuYWfkL9dKkbs' => 42 buffer accounts -``` - -### Reclaiming program data accounts - -You may now realize that program data accounts (the accounts that store the executable byte-code for an on-chain program) can also be closed. - -> **Note:** This does _not_ mean that _program accounts_ can be closed (those are immutable and can never be reclaimed, but it's fine they're pretty small). It's also important to keep in mind that once program data accounts are deleted, they can never be recreated for an existing program. Therefore, the corresponding program (and its program id) for any closed program data account is effectively disabled forever and may not be re-deployed - -While it would be uncommon for developers to need to close program data accounts since they can be rewritten during upgrades, one potential scenario is that since program data accounts can't be _resized_. You may wish to deploy your program at a new address to accommodate larger executables. - -The ability to reclaim program data account rent deposits also makes testing and experimentation on the `mainnet-beta` cluster a lot less costly since you could reclaim everything except the transaction fees and a small amount of rent for the program account. Lastly, this could help developers recover most of their funds if they mistakenly deploy a program at an unintended address or on the wrong cluster. - -To view the programs which are owned by your wallet address, you can run: - -```bash -solana -V # must be 1.7.11 or higher! -solana program show --programs --keypair ~/.config/solana/MY_KEYPAIR.json - -Program Id | Slot | Authority | Balance -CN5x9WEusU6pNH66G22SnspVx4cogWLqMfmb85Z3GW7N | 53796672 | 2nr1bHFT86W9tGnyvmYW4vcHKsQB3sVQfnddasz4kExM | 0.54397272 SOL -``` - -To close those program data accounts and reclaim their SOL balance, you can run: - -```bash -solana program close --programs --keypair ~/.config/solana/MY_KEYPAIR.json -``` - -You might be concerned about this feature allowing malicious actors to close a program in a way that negatively impacts end users. While this is a valid concern in general, closing program data accounts doesn't make this any more exploitable than was already possible. - -Even without the ability to close a program data account, any upgradeable program could be upgraded to a no-op implementation and then have its upgrade authority cleared to make it immutable forever. This new feature for closing program data accounts merely adds the ability to reclaim the rent deposit, disabling a program was already technically possible. diff --git a/docs/src/developing/on-chain-programs/developing-c.md b/docs/src/developing/on-chain-programs/developing-c.md deleted file mode 100644 index cffbd1006b..0000000000 --- a/docs/src/developing/on-chain-programs/developing-c.md +++ /dev/null @@ -1,190 +0,0 @@ ---- -title: "Developing with C" ---- - -Solana supports writing on-chain programs using the C and C++ programming -languages. - -## Project Layout - -C projects are laid out as follows: - -``` -/src/ -/makefile -``` - -The `makefile` should contain the following: - -```bash -OUT_DIR := -include ~/.local/share/solana/install/active_release/bin/sdk/sbf/c/sbf.mk -``` - -The sbf-sdk may not be in the exact place specified above but if you setup your -environment per [How to Build](#how-to-build) then it should be. - -## How to Build - -First setup the environment: - -- Install the latest Rust stable from https://rustup.rs -- Install the latest [Solana command-line tools](../../cli/install-solana-cli-tools.md) - -Then build using make: - -```bash -make -C -``` - -## How to Test - -Solana uses the [Criterion](https://github.com/Snaipe/Criterion) test framework -and tests are executed each time the program is built [How to -Build](#how-to-build). - -To add tests, create a new file next to your source file named `test_.c` -and populate it with criterion test cases. See the [Criterion docs](https://criterion.readthedocs.io/en/master) -for information on how to write a test case. - -## Program Entrypoint - -Programs export a known entrypoint symbol which the Solana runtime looks up and -calls when invoking a program. Solana supports multiple versions of the SBF loader and the entrypoints may vary between them. -Programs must be written for and deployed to the same loader. For more details -see the [FAQ section on Loaders](./faq.md#loaders). - -Currently there are two supported loaders [SBF -Loader](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader.rs#L17) -and [SBF loader -deprecated](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader_deprecated.rs#L14). - -They both have the same raw entrypoint definition, the following is the raw -symbol that the runtime looks up and calls: - -```c -extern uint64_t entrypoint(const uint8_t *input) -``` - -This entrypoint takes a generic byte array which contains the serialized program -parameters (program id, accounts, instruction data, etc...). To deserialize the -parameters each loader contains its own [helper function](#Serialization). - -### Serialization - -Each loader provides a helper function that deserializes the program's input -parameters into C types: - -- [SBF Loader - deserialization](https://github.com/solana-labs/solana/blob/d2ee9db2143859fa5dc26b15ee6da9c25cc0429c/sdk/sbf/c/inc/solana_sdk.h#L304) -- [SBF Loader deprecated - deserialization](https://github.com/solana-labs/solana/blob/8415c22b593f164020adc7afe782e8041d756ddf/sdk/sbf/c/inc/deserialize_deprecated.h#L25) - -Some programs may want to perform deserialization themselves, and they can by -providing their own implementation of the [raw entrypoint](#program-entrypoint). -Take note that the provided deserialization functions retain references back to -the serialized byte array for variables that the program is allowed to modify -(lamports, account data). The reason for this is that upon return the loader -will read those modifications so they may be committed. If a program implements -their own deserialization function they need to ensure that any modifications -the program wishes to commit must be written back into the input byte array. - -Details on how the loader serializes the program inputs can be found in the -[Input Parameter Serialization](./faq.md#input-parameter-serialization) docs. - -## Data Types - -The loader's deserialization helper function populates the -[SolParameters](https://github.com/solana-labs/solana/blob/8415c22b593f164020adc7afe782e8041d756ddf/sdk/sbf/c/inc/solana_sdk.h#L276) -structure: - -```c -/** - * Structure that the program's entrypoint input data is deserialized into. - */ -typedef struct { - SolAccountInfo* ka; /** Pointer to an array of SolAccountInfo, must already - point to an array of SolAccountInfos */ - uint64_t ka_num; /** Number of SolAccountInfo entries in `ka` */ - const uint8_t *data; /** pointer to the instruction data */ - uint64_t data_len; /** Length in bytes of the instruction data */ - const SolPubkey *program_id; /** program_id of the currently executing program */ -} SolParameters; -``` - -'ka' is an ordered array of the accounts referenced by the instruction and -represented as a -[SolAccountInfo](https://github.com/solana-labs/solana/blob/8415c22b593f164020adc7afe782e8041d756ddf/sdk/sbf/c/inc/solana_sdk.h#L173) -structures. An account's place in the array signifies its meaning, for example, -when transferring lamports an instruction may define the first account as the -source and the second as the destination. - -The members of the `SolAccountInfo` structure are read-only except for -`lamports` and `data`. Both may be modified by the program in accordance with -the [runtime enforcement -policy](developing/programming-model/accounts.md#policy). When an instruction -reference the same account multiple times there may be duplicate -`SolAccountInfo` entries in the array but they both point back to the original -input byte array. A program should handle these cases delicately to avoid -overlapping read/writes to the same buffer. If a program implements their own -deserialization function care should be taken to handle duplicate accounts -appropriately. - -`data` is the general purpose byte array from the [instruction's instruction -data](developing/programming-model/transactions.md#instruction-data) being -processed. - -`program_id` is the public key of the currently executing program. - -## Heap - -C programs can allocate memory via the system call -[`calloc`](https://github.com/solana-labs/solana/blob/c3d2d2134c93001566e1e56f691582f379b5ae55/sdk/sbf/c/inc/solana_sdk.h#L245) -or implement their own heap on top of the 32KB heap region starting at virtual -address x300000000. The heap region is also used by `calloc` so if a program -implements their own heap it should not also call `calloc`. - -## Logging - -The runtime provides two system calls that take data and log it to the program -logs. - -- [`sol_log(const char*)`](https://github.com/solana-labs/solana/blob/d2ee9db2143859fa5dc26b15ee6da9c25cc0429c/sdk/sbf/c/inc/solana_sdk.h#L128) -- [`sol_log_64(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)`](https://github.com/solana-labs/solana/blob/d2ee9db2143859fa5dc26b15ee6da9c25cc0429c/sdk/sbf/c/inc/solana_sdk.h#L134) - -The [debugging](debugging.md#logging) section has more information about working -with program logs. - -## Compute Budget - -Use the system call `sol_remaining_compute_units()` to return a `u64` indicating -the number of compute units remaining for this transaction. - -Use the system call -[`sol_log_compute_units()`](https://github.com/solana-labs/solana/blob/d3a3a7548c857f26ec2cb10e270da72d373020ec/sdk/sbf/c/inc/solana_sdk.h#L140) -to log a message containing the remaining number of compute units the program -may consume before execution is halted - -See [compute budget](developing/programming-model/runtime.md#compute-budget) -for more information. - -## ELF Dump - -The SBF shared object internals can be dumped to a text file to gain more -insight into a program's composition and what it may be doing at runtime. The -dump will contain both the ELF information as well as a list of all the symbols -and the instructions that implement them. Some of the SBF loader's error log -messages will reference specific instruction numbers where the error occurred. -These references can be looked up in the ELF dump to identify the offending -instruction and its context. - -To create a dump file: - -```bash -$ cd -$ make dump_ -``` - -## Examples - -The [Solana Program Library github](https://github.com/solana-labs/solana-program-library/tree/master/examples/c) repo contains a collection of C examples diff --git a/docs/src/developing/on-chain-programs/developing-rust.md b/docs/src/developing/on-chain-programs/developing-rust.md deleted file mode 100644 index d1f8423ecd..0000000000 --- a/docs/src/developing/on-chain-programs/developing-rust.md +++ /dev/null @@ -1,395 +0,0 @@ ---- -title: "Developing with Rust" ---- - -Solana supports writing on-chain programs using the -[Rust](https://www.rust-lang.org/) programming language. - -## Project Layout - -Solana Rust programs follow the typical [Rust project -layout](https://doc.rust-lang.org/cargo/guide/project-layout.html): - -``` -/inc/ -/src/ -/Cargo.toml -``` - -Solana Rust programs may depend directly on each other in order to gain access -to instruction helpers when making [cross-program invocations](developing/programming-model/calling-between-programs.md#cross-program-invocations). -When doing so it's important to not pull in the dependent program's entrypoint -symbols because they may conflict with the program's own. To avoid this, -programs should define an `no-entrypoint` feature in `Cargo.toml` and use -to exclude the entrypoint. - -- [Define the - feature](https://github.com/solana-labs/solana-program-library/blob/fca9836a2c8e18fc7e3595287484e9acd60a8f64/token/program/Cargo.toml#L12) -- [Exclude the - entrypoint](https://github.com/solana-labs/solana-program-library/blob/fca9836a2c8e18fc7e3595287484e9acd60a8f64/token/program/src/lib.rs#L12) - -Then when other programs include this program as a dependency, they should do so -using the `no-entrypoint` feature. - -- [Include without - entrypoint](https://github.com/solana-labs/solana-program-library/blob/fca9836a2c8e18fc7e3595287484e9acd60a8f64/token-swap/program/Cargo.toml#L22) - -## Project Dependencies - -At a minimum, Solana Rust programs must pull in the -[solana-program](https://crates.io/crates/solana-program) crate. - -Solana SBF programs have some [restrictions](#restrictions) that may prevent the -inclusion of some crates as dependencies or require special handling. - -For example: - -- Crates that require the architecture be a subset of the ones supported by the - official toolchain. There is no workaround for this unless that crate is - forked and SBF added to that those architecture checks. -- Crates may depend on `rand` which is not supported in Solana's deterministic - program environment. To include a `rand` dependent crate refer to [Depending - on Rand](#depending-on-rand). -- Crates may overflow the stack even if the stack overflowing code isn't - included in the program itself. For more information refer to - [Stack](./faq.md#stack). - -## How to Build - -First setup the environment: - -- Install the latest Rust stable from https://rustup.rs/ -- Install the latest [Solana command-line tools](../../cli/install-solana-cli-tools.md) - -The normal cargo build is available for building programs against your host -machine which can be used for unit testing: - -```bash -$ cargo build -``` - -To build a specific program, such as SPL Token, for the Solana SBF target which -can be deployed to the cluster: - -```bash -$ cd -$ cargo build-bpf -``` - -## How to Test - -Solana programs can be unit tested via the traditional `cargo test` mechanism by -exercising program functions directly. - -To help facilitate testing in an environment that more closely matches a live -cluster, developers can use the -[`program-test`](https://crates.io/crates/solana-program-test) crate. The -`program-test` crate starts up a local instance of the runtime and allows tests -to send multiple transactions while keeping state for the duration of the test. - -For more information the [test in sysvar -example](https://github.com/solana-labs/solana-program-library/blob/master/examples/rust/sysvar/tests/functional.rs) -shows how an instruction containing sysvar account is sent and processed by the -program. - -## Program Entrypoint - -Programs export a known entrypoint symbol which the Solana runtime looks up and -calls when invoking a program. Solana supports multiple versions of the BPF -loader and the entrypoints may vary between them. -Programs must be written for and deployed to the same loader. For more details -see the [FAQ section on Loaders](./faq.md#loaders). - -Currently there are two supported loaders [BPF -Loader](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/bpf_loader.rs#L17) -and [BPF loader -deprecated](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/bpf_loader_deprecated.rs#L14) - -They both have the same raw entrypoint definition, the following is the raw -symbol that the runtime looks up and calls: - -```rust -#[no_mangle] -pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64; -``` - -This entrypoint takes a generic byte array which contains the serialized program -parameters (program id, accounts, instruction data, etc...). To deserialize the -parameters each loader contains its own wrapper macro that exports the raw -entrypoint, deserializes the parameters, calls a user defined instruction -processing function, and returns the results. - -You can find the entrypoint macros here: - -- [BPF Loader's entrypoint - macro](https://github.com/solana-labs/solana/blob/9b1199cdb1b391b00d510ed7fc4866bdf6ee4eb3/sdk/program/src/entrypoint.rs#L42) -- [BPF Loader deprecated's entrypoint - macro](https://github.com/solana-labs/solana/blob/9b1199cdb1b391b00d510ed7fc4866bdf6ee4eb3/sdk/program/src/entrypoint_deprecated.rs#L38) - -The program defined instruction processing function that the entrypoint macros -call must be of this form: - -```rust -pub type ProcessInstruction = - fn(program_id: &Pubkey, accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResult; -``` - -### Parameter Deserialization - -Each loader provides a helper function that deserializes the program's input -parameters into Rust types. The entrypoint macros automatically calls the -deserialization helper: - -- [BPF Loader - deserialization](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/entrypoint.rs#L146) -- [BPF Loader deprecated - deserialization](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/entrypoint_deprecated.rs#L57) - -Some programs may want to perform deserialization themselves and they can by -providing their own implementation of the [raw entrypoint](#program-entrypoint). -Take note that the provided deserialization functions retain references back to -the serialized byte array for variables that the program is allowed to modify -(lamports, account data). The reason for this is that upon return the loader -will read those modifications so they may be committed. If a program implements -their own deserialization function they need to ensure that any modifications -the program wishes to commit be written back into the input byte array. - -Details on how the loader serializes the program inputs can be found in the -[Input Parameter Serialization](./faq.md#input-parameter-serialization) docs. - -### Data Types - -The loader's entrypoint macros call the program defined instruction processor -function with the following parameters: - -```rust -program_id: &Pubkey, -accounts: &[AccountInfo], -instruction_data: &[u8] -``` - -The program id is the public key of the currently executing program. - -The accounts is an ordered slice of the accounts referenced by the instruction -and represented as an -[AccountInfo](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/account_info.rs#L12) -structures. An account's place in the array signifies its meaning, for example, -when transferring lamports an instruction may define the first account as the -source and the second as the destination. - -The members of the `AccountInfo` structure are read-only except for `lamports` -and `data`. Both may be modified by the program in accordance with the [runtime -enforcement policy](developing/programming-model/accounts.md#policy). Both of -these members are protected by the Rust `RefCell` construct, so they must be -borrowed to read or write to them. The reason for this is they both point back -to the original input byte array, but there may be multiple entries in the -accounts slice that point to the same account. Using `RefCell` ensures that the -program does not accidentally perform overlapping read/writes to the same -underlying data via multiple `AccountInfo` structures. If a program implements -their own deserialization function care should be taken to handle duplicate -accounts appropriately. - -The instruction data is the general purpose byte array from the [instruction's -instruction data](developing/programming-model/transactions.md#instruction-data) -being processed. - -## Heap - -Rust programs implement the heap directly by defining a custom -[`global_allocator`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/entrypoint.rs#L72) - -Programs may implement their own `global_allocator` based on its specific needs. -Refer to the [custom heap example](#examples) for more information. - -## Restrictions - -On-chain Rust programs support most of Rust's libstd, libcore, and liballoc, as -well as many 3rd party crates. - -There are some limitations since these programs run in a resource-constrained, -single-threaded environment, as well as being deterministic: - -- No access to - - `rand` - - `std::fs` - - `std::net` - - `std::future` - - `std::process` - - `std::sync` - - `std::task` - - `std::thread` - - `std::time` -- Limited access to: - - `std::hash` - - `std::os` -- Bincode is extremely computationally expensive in both cycles and call depth - and should be avoided -- String formatting should be avoided since it is also computationally - expensive. -- No support for `println!`, `print!`, the Solana [logging helpers](#logging) - should be used instead. -- The runtime enforces a limit on the number of instructions a program can - execute during the processing of one instruction. See - [computation budget](developing/programming-model/runtime.md#compute-budget) for more - information. - -## Depending on Rand - -Programs are constrained to run deterministically, so random numbers are not -available. Sometimes a program may depend on a crate that depends itself on -`rand` even if the program does not use any of the random number functionality. -If a program depends on `rand`, the compilation will fail because there is no -`get-random` support for Solana. The error will typically look like this: - -``` -error: target is not supported, for more information see: https://docs.rs/getrandom/#unsupported-targets - --> /Users/jack/.cargo/registry/src/github.com-1ecc6299db9ec823/getrandom-0.1.14/src/lib.rs:257:9 - | -257 | / compile_error!("\ -258 | | target is not supported, for more information see: \ -259 | | https://docs.rs/getrandom/#unsupported-targets\ -260 | | "); - | |___________^ -``` - -To work around this dependency issue, add the following dependency to the -program's `Cargo.toml`: - -``` -getrandom = { version = "0.1.14", features = ["dummy"] } -``` - -or if the dependency is on getrandom v0.2 add: - -``` -getrandom = { version = "0.2.2", features = ["custom"] } -``` - -## Logging - -Rust's `println!` macro is computationally expensive and not supported. Instead -the helper macro -[`msg!`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/log.rs#L33) -is provided. - -`msg!` has two forms: - -```rust -msg!("A string"); -``` - -or - -```rust -msg!(0_64, 1_64, 2_64, 3_64, 4_64); -``` - -Both forms output the results to the program logs. If a program so wishes they -can emulate `println!` by using `format!`: - -```rust -msg!("Some variable: {:?}", variable); -``` - -The [debugging](debugging.md#logging) section has more information about working -with program logs the [Rust examples](#examples) contains a logging example. - -## Panicking - -Rust's `panic!`, `assert!`, and internal panic results are printed to the -[program logs](debugging.md#logging) by default. - -``` -INFO solana_runtime::message_processor] Finalized account CGLhHSuWsp1gT4B7MY2KACqp9RUwQRhcUFfVSuxpSajZ -INFO solana_runtime::message_processor] Call SBF program CGLhHSuWsp1gT4B7MY2KACqp9RUwQRhcUFfVSuxpSajZ -INFO solana_runtime::message_processor] Program log: Panicked at: 'assertion failed: `(left == right)` - left: `1`, - right: `2`', rust/panic/src/lib.rs:22:5 -INFO solana_runtime::message_processor] SBF program consumed 5453 of 200000 units -INFO solana_runtime::message_processor] SBF program CGLhHSuWsp1gT4B7MY2KACqp9RUwQRhcUFfVSuxpSajZ failed: BPF program panicked -``` - -### Custom Panic Handler - -Programs can override the default panic handler by providing their own -implementation. - -First define the `custom-panic` feature in the program's `Cargo.toml` - -```toml -[features] -default = ["custom-panic"] -custom-panic = [] -``` - -Then provide a custom implementation of the panic handler: - -```rust -#[cfg(all(feature = "custom-panic", target_os = "solana"))] -#[no_mangle] -fn custom_panic(info: &core::panic::PanicInfo<'_>) { - solana_program::msg!("program custom panic enabled"); - solana_program::msg!("{}", info); -} -``` - -In the above snippit, the default implementation is shown, but developers may -replace that with something that better suits their needs. - -One of the side effects of supporting full panic messages by default is that -programs incur the cost of pulling in more of Rust's `libstd` implementation -into program's shared object. Typical programs will already be pulling in a -fair amount of `libstd` and may not notice much of an increase in the shared -object size. But programs that explicitly attempt to be very small by avoiding -`libstd` may take a significant impact (~25kb). To eliminate that impact, -programs can provide their own custom panic handler with an empty -implementation. - -```rust -#[cfg(all(feature = "custom-panic", target_os = "solana"))] -#[no_mangle] -fn custom_panic(info: &core::panic::PanicInfo<'_>) { - // Do nothing to save space -} -``` - -## Compute Budget - -Use the system call `sol_remaining_compute_units()` to return a `u64` indicating -the number of compute units remaining for this transaction. - -Use the system call -[`sol_log_compute_units()`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/log.rs#L141) -to log a message containing the remaining number of compute units the program -may consume before execution is halted - -See [compute budget](developing/programming-model/runtime.md#compute-budget) -for more information. - -## ELF Dump - -The SBF shared object internals can be dumped to a text file to gain more -insight into a program's composition and what it may be doing at runtime. The -dump will contain both the ELF information as well as a list of all the symbols -and the instructions that implement them. Some of the BPF loader's error log -messages will reference specific instruction numbers where the error occurred. -These references can be looked up in the ELF dump to identify the offending -instruction and its context. - -To create a dump file: - -```bash -$ cd -$ cargo build-bpf --dump -``` - -## Examples - -The [Solana Program Library -GitHub](https://github.com/solana-labs/solana-program-library/tree/master/examples/rust) -repo contains a collection of Rust examples. - -The [Solana Developers -Program Examples GitHub](https://github.com/solana-developers/program-examples) -repo also contains a collection of beginner to intermediate Rust program -examples. \ No newline at end of file diff --git a/docs/src/developing/on-chain-programs/examples.md b/docs/src/developing/on-chain-programs/examples.md deleted file mode 100644 index 1aaf154c74..0000000000 --- a/docs/src/developing/on-chain-programs/examples.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: "Program Examples" ---- - -## Break - -[Break](https://break.solana.com/) is a React app that gives users a visceral -feeling for just how fast and high-performance the Solana network really is. Can -you _break_ the Solana blockchain? During a 15 second play-though, each click of -a button or keystroke sends a new transaction to the cluster. Smash the keyboard -as fast as you can and watch your transactions get finalized in real time while -the network takes it all in stride! - -Break can be played on our Devnet, Testnet and Mainnet Beta networks. Plays are -free on Devnet and Testnet, where the session is funded by a network faucet. On -Mainnet Beta, users pay to play 0.08 SOL per game. The session account can be -funded by a local keystore wallet or by scanning a QR code from Trust Wallet to -transfer the tokens. - -[Click here to play Break](https://break.solana.com/) - -### Build and Run - -First fetch the latest version of the example code: - -```bash -$ git clone https://github.com/solana-labs/break.git -$ cd break -``` - -Next, follow the steps in the git repository's -[README](https://github.com/solana-labs/break/blob/master/README.md). - -## Language Specific - -- [Rust](developing-rust.md#examples) -- [C](developing-c.md#examples) diff --git a/docs/src/developing/on-chain-programs/faq.md b/docs/src/developing/on-chain-programs/faq.md deleted file mode 100644 index 04093f64c5..0000000000 --- a/docs/src/developing/on-chain-programs/faq.md +++ /dev/null @@ -1,215 +0,0 @@ ---- -title: "FAQ" ---- - -When writing or interacting with Solana programs, there are common questions or -challenges that often come up. Below are resources to help answer these -questions. - -If not addressed here, ask on [StackExchange](https://solana.stackexchange.com/questions/ask?tags=solana-program) with the `solana-program` tag. - -## Limitations - -Developing programs on the Solana blockchain have some inherent limitation associated with them. Below is a list of common limitation that you may run into. - -See [Limitations of developing programs](./limitations.md) for more details - -## Berkeley Packet Filter (BPF) - -Solana on-chain programs are compiled via the [LLVM compiler infrastructure](https://llvm.org/) to an [Executable and Linkable Format (ELF)](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) containing -a variation of the [Berkeley Packet Filter (BPF)](https://en.wikipedia.org/wiki/Berkeley_Packet_Filter) bytecode. - -Because Solana uses the LLVM compiler infrastructure, a program may be written in any programming language that can target the LLVM's BPF backend. - -BPF provides an efficient [instruction set](https://github.com/iovisor/bpf-docs/blob/master/eBPF.md) that can be executed in an interpreted virtual machine or as efficient just-in-time compiled native instructions. - -## Memory map - -The virtual address memory map used by Solana SBF programs is fixed and laid out -as follows - -- Program code starts at 0x100000000 -- Stack data starts at 0x200000000 -- Heap data starts at 0x300000000 -- Program input parameters start at 0x400000000 - -The above virtual addresses are start addresses but programs are given access to -a subset of the memory map. The program will panic if it attempts to read or -write to a virtual address that it was not granted access to, and an -`AccessViolation` error will be returned that contains the address and size of -the attempted violation. - -## InvalidAccountData - -This program error can happen for a lot of reasons. Usually, it's caused by -passing an account to the program that the program is not expecting, either in -the wrong position in the instruction or an account not compatible with the -instruction being executed. - -An implementation of a program might also cause this error when performing a -cross-program instruction and forgetting to provide the account for the program -that you are calling. - -## InvalidInstructionData - -This program error can occur while trying to deserialize the instruction, check -that the structure passed in matches exactly the instruction. There may be some -padding between fields. If the program implements the Rust `Pack` trait then try -packing and unpacking the instruction type `T` to determine the exact encoding -the program expects: - -https://github.com/solana-labs/solana/blob/v1.4/sdk/program/src/program_pack.rs - -## MissingRequiredSignature - -Some instructions require the account to be a signer; this error is returned if -an account is expected to be signed but is not. - -An implementation of a program might also cause this error when performing a -cross-program invocation that requires a signed program address, but the passed -signer seeds passed to [`invoke_signed`](developing/programming-model/calling-between-programs.md) -don't match the signer seeds used to create the program address -[`create_program_address`](developing/programming-model/calling-between-programs.md#program-derived-addresses). - -## `rand` Rust dependency causes compilation failure - -See [Rust Project Dependencies](developing-rust.md#project-dependencies) - -## Rust restrictions - -See [Rust restrictions](developing-rust.md#restrictions) - -## Stack - -SBF uses stack frames instead of a variable stack pointer. Each stack frame is -4KB in size. - -If a program violates that stack frame size, the compiler will report the -overrun as a warning. - -For example: - -``` -Error: Function _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E Stack offset of -30728 exceeded max offset of -4096 by 26632 bytes, please minimize large stack variables -``` - -The message identifies which symbol is exceeding its stack frame, but the name -might be mangled if it is a Rust or C++ symbol. - -> To demangle a Rust symbol use [rustfilt](https://github.com/luser/rustfilt). - -The above warning came from a Rust program, so the demangled symbol name is: - -```bash -rustfilt _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E -curve25519_dalek::edwards::EdwardsBasepointTable::create -``` - -To demangle a C++ symbol use `c++filt` from binutils. - -The reason a warning is reported rather than an error is because some dependent -crates may include functionality that violates the stack frame restrictions even -if the program doesn't use that functionality. If the program violates the stack -size at runtime, an `AccessViolation` error will be reported. - -SBF stack frames occupy a virtual address range starting at `0x200000000`. - -## Heap size - -Programs have access to a runtime heap either directly in C or via the Rust -`alloc` APIs. To facilitate fast allocations, a simple 32KB bump heap is -utilized. The heap does not support `free` or `realloc` so use it wisely. - -Internally, programs have access to the 32KB memory region starting at virtual -address 0x300000000 and may implement a custom heap based on the program's -specific needs. - -- [Rust program heap usage](developing-rust.md#heap) -- [C program heap usage](developing-c.md#heap) - -## Loaders - -Programs are deployed with and executed by runtime loaders, currently there are -two supported loaders [BPF -Loader](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader.rs#L17) -and [BPF loader -deprecated](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader_deprecated.rs#L14) - -Loaders may support different application binary interfaces so developers must -write their programs for and deploy them to the same loader. If a program -written for one loader is deployed to a different one the result is usually a -`AccessViolation` error due to mismatched deserialization of the program's input -parameters. - -For all practical purposes program should always be written to target the latest -BPF loader and the latest loader is the default for the command-line interface -and the javascript APIs. - -For language specific information about implementing a program for a particular -loader see: - -- [Rust program entrypoints](developing-rust.md#program-entrypoint) -- [C program entrypoints](developing-c.md#program-entrypoint) - -### Deployment - -SBF program deployment is the process of uploading a BPF shared object into a -program account's data and marking the account executable. A client breaks the -SBF shared object into smaller pieces and sends them as the instruction data of -[`Write`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/sdk/program/src/loader_instruction.rs#L13) -instructions to the loader where loader writes that data into the program's -account data. Once all the pieces are received the client sends a -[`Finalize`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/sdk/program/src/loader_instruction.rs#L30) -instruction to the loader, the loader then validates that the SBF data is valid -and marks the program account as _executable_. Once the program account is -marked executable, subsequent transactions may issue instructions for that -program to process. - -When an instruction is directed at an executable SBF program the loader -configures the program's execution environment, serializes the program's input -parameters, calls the program's entrypoint, and reports any errors encountered. - -For further information see [deploying](deploying.md) - -### Input Parameter Serialization - -SBF loaders serialize the program input parameters into a byte array that is -then passed to the program's entrypoint, where the program is responsible for -deserializing it on-chain. One of the changes between the deprecated loader and -the current loader is that the input parameters are serialized in a way that -results in various parameters falling on aligned offsets within the aligned byte -array. This allows deserialization implementations to directly reference the -byte array and provide aligned pointers to the program. - -For language specific information about serialization see: - -- [Rust program parameter - deserialization](developing-rust.md#parameter-deserialization) -- [C program parameter - deserialization](developing-c.md#parameter-deserialization) - -The latest loader serializes the program input parameters as follows (all -encoding is little endian): - -- 8 bytes unsigned number of accounts -- For each account - - 1 byte indicating if this is a duplicate account, if not a duplicate then - the value is 0xff, otherwise the value is the index of the account it is a - duplicate of. - - If duplicate: 7 bytes of padding - - If not duplicate: - - 1 byte boolean, true if account is a signer - - 1 byte boolean, true if account is writable - - 1 byte boolean, true if account is executable - - 4 bytes of padding - - 32 bytes of the account public key - - 32 bytes of the account's owner public key - - 8 bytes unsigned number of lamports owned by the account - - 8 bytes unsigned number of bytes of account data - - x bytes of account data - - 10k bytes of padding, used for realloc - - enough padding to align the offset to 8 bytes. - - 8 bytes rent epoch -- 8 bytes of unsigned number of instruction data -- x bytes of instruction data -- 32 bytes of the program id diff --git a/docs/src/developing/on-chain-programs/limitations.md b/docs/src/developing/on-chain-programs/limitations.md deleted file mode 100644 index f5c5e17427..0000000000 --- a/docs/src/developing/on-chain-programs/limitations.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: "Limitations" ---- - -Developing programs on the Solana blockchain have some inherent limitation associated with them. Below is a list of common limitation that you may run into. - -## Rust libraries - -Since Rust based on-chain programs must run be deterministic while running in a resource-constrained, single-threaded environment, they have some limitations on various libraries. - -See [Developing with Rust - Restrictions](./developing-rust.md#restrictions) for a detailed breakdown these restrictions and limitations. - -## Compute budget - -To prevent abuse of the blockchain's computational resources, each transaction is allocated a [compute budget](./../../terminology.md#compute-budget). Exceeding this compute budget will result in the transaction failing. - -See [computational constraints](../programming-model/runtime.md#compute-budget) in the Runtime for more specific details. - -## Call stack depth - `CallDepthExceeded` error - -Solana programs are constrained to run quickly, and to facilitate this, the program's call stack is limited to a max depth of **64 frames**. - -When a program exceeds the allowed call stack depth limit, it will receive the `CallDepthExceeded` error. - -## CPI call depth - `CallDepth` error - -Cross-program invocations allow programs to invoke other programs directly, but the depth is constrained currently to `4`. - -When a program exceeds the allowed [cross-program invocation call depth](../programming-model/calling-between-programs.md#call-depth), it will receive a `CallDepth` error - -## Float Rust types support - -Programs support a limited subset of Rust's float operations. If a program -attempts to use a float operation that is not supported, the runtime will report -an unresolved symbol error. - -Float operations are performed via software libraries, specifically LLVM's float -built-ins. Due to the software emulated, they consume more compute units than -integer operations. In general, fixed point operations are recommended where -possible. - -The Solana Program Library math tests will report the performance of some math -operations: https://github.com/solana-labs/solana-program-library/tree/master/libraries/math - -To run the test: sync the repo and run: - -```sh -cargo test-sbf -- --nocapture --test-threads=1 -``` - -Recent results show the float operations take more instructions compared to -integers equivalents. Fixed point implementations may vary but will also be -less than the float equivalents: - -``` - u64 f32 -Multiply 8 176 -Divide 9 219 -``` - -## Static writable data - -Program shared objects do not support writable shared data. Programs are shared -between multiple parallel executions using the same shared read-only code and -data. This means that developers should not include any static writable or -global variables in programs. In the future a copy-on-write mechanism could be -added to support writable data. - -## Signed division - -The SBF instruction set does not support -[signed division](https://www.kernel.org/doc/html/latest/bpf/bpf_design_QA.Html#q-why-there-is-no-bpf-sdiv-for-signed-divide-operation). Adding a signed division instruction is a consideration. diff --git a/docs/src/developing/on-chain-programs/overview.md b/docs/src/developing/on-chain-programs/overview.md deleted file mode 100644 index af92a05128..0000000000 --- a/docs/src/developing/on-chain-programs/overview.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: "Overview of Writing Programs" -sidebar_label: "Overview" ---- - -Developers can write and deploy their own programs to the Solana blockchain. While developing these "on-chain" programs can seem cumbersome, the entire process can be broadly summarized into a few key steps. - -## Solana Development Lifecycle - -1. Setup your development environment -2. Write your program -3. Compile the program -4. Generate the program's public address -5. Deploy the program - -### 1. Setup your development environment - -The most robust way of getting started with Solana development, is [installing the Solana CLI](./../../cli/install-solana-cli-tools.md) tools on your local computer. This will allow you to have the most powerful development environment. - -Some developers may also opt for using [Solana Playground](https://beta.solpg.io/), a browser based IDE. It will let you write, build, and deploy on-chain programs. All from your browser. No installation needed. - -### 2. Write your program - -Writing Solana programs is most commonly done so using the Rust language. These Rust programs are effectively the same as creating a traditional [Rust library](https://doc.rust-lang.org/rust-by-example/crates/lib.html). - -> You can read more about other [supported languages](#support-languages) below. - -### 3. Compile the program - -Once the program is written, it must be complied down to [Berkley Packet Filter](./faq.md#berkeley-packet-filter-bpf) byte-code that will then be deployed to the blockchain. - -### 4. Generate the program's public address - -Using the [Solana CLI](./../../cli/install-solana-cli-tools.md), the developer will generate a new unique [Keypair](./../../terminology.md#keypair) for the new program. The public address (aka [Pubkey](./../../terminology.md#public-key-pubkey)) from this Keypair will be used on-chain as the program's public address (aka [`programId`](./../../terminology.md#program-id)). - -### 5. Deploying the program - -Then again using the CLI, the compiled program can be deployed to the selected blockchain cluster by creating many transactions containing the program's byte-code. Due to the transaction memory size limitations, each transaction effectively sends small chunks of the program to the blockchain in a rapid-fire manner. - -Once the entire program has been sent to the blockchain, a final transaction is sent to write all of the buffered byte-code to the program's data account. This either mark the new program as [`executable`](./../programming-model/accounts.md#executable), or complete the process to upgrade an existing program (if it already existed). - -## Support languages - -Solana programs are typically written in the [Rust language](./developing-rust.md), but [C/C++](./developing-c.md) are also supported. - -There are also various community driven efforts to enable writing on-chain programs using other languages, including: - -- Python via [Seahorse](https://seahorse-lang.org/) (that acts as a wrapper the Rust based Anchor framework) - -## Example programs - -You can also explore the [Program Examples](./examples.md) for examples of on-chain programs. - -## Limitations - -As you dive deeper into program development, it is important to understand some of the important limitations associated with on-chain programs. - -Read more details on the [Limitations](./limitations.md) page - -## Frequently asked questions - -Discover many of the [frequently asked questions](./faq.md) other developers have about writing/understanding Solana programs. diff --git a/docs/src/developing/programming-model/accounts.md b/docs/src/developing/programming-model/accounts.md deleted file mode 100644 index 09265b7bca..0000000000 --- a/docs/src/developing/programming-model/accounts.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: "Accounts" ---- - -## Storing State between Transactions - -If the program needs to store state between transactions, it does so using -_accounts_. Accounts are similar to files in operating systems such as Linux in -that they may hold arbitrary data that persists beyond -the lifetime of a program. Also like a file, an account includes metadata that -tells the runtime who is allowed to access the data and how. - -Unlike a file, the account includes metadata for the lifetime of the file. That -lifetime is expressed by a number of fractional native -tokens called _lamports_. Accounts are held in validator memory and pay -["rent"](#rent) to stay there. Each validator periodically scans all accounts -and collects rent. Any account that drops to zero lamports is purged. Accounts -can also be marked [rent-exempt](#rent-exemption) if they contain a sufficient -number of lamports. - -In the same way that a Linux user uses a path to look up a file, a Solana client -uses an _address_ to look up an account. The address is a 256-bit public key. - -## Signers - -Transactions include one or more digital [signatures](terminology.md#signature) -each corresponding to an account address referenced by the transaction. Each of these -addresses must be the public key of an ed25519 keypair, and the signature signifies -that the holder of the matching private key signed, and thus, "authorized" the transaction. -In this case, the account is referred to as a _signer_. Whether an account is a signer or not -is communicated to the program as part of the account's metadata. Programs can -then use that information to make authority decisions. - -## Read-only - -Transactions can [indicate](transactions.md#message-header-format) that some of -the accounts it references be treated as _read-only accounts_ in order to enable -parallel account processing between transactions. The runtime permits read-only -accounts to be read concurrently by multiple programs. If a program attempts to -modify a read-only account, the transaction is rejected by the runtime. - -## Executable - -If an account is marked "executable" in its metadata, then it is considered a -program which can be executed by including the account's public key in an -instruction's [program id](transactions.md#program-id). Accounts are marked as -executable during a successful program deployment process by the loader that -owns the account. When a program is deployed to the execution engine (SBF deployment), -the loader determines that the bytecode in the account's data is valid. -If so, the loader permanently marks the program account as executable. - -If a program is marked as final (non-upgradeable), the runtime enforces that the -account's data (the program) is immutable. Through the upgradeable loader, it is -possible to upload a totally new program to an existing program address. - -## Creating - -To create an account, a client generates a _keypair_ and registers its public key -using the `SystemProgram::CreateAccount` instruction with a fixed -storage size in bytes preallocated. -The current maximum size of an account's data is 10 MiB, which can be changed -(increased or decreased) at a rate over all accounts of 20 MiB per transaction, -and the size can be increased by 10 KiB per account and per instruction. - -An account address can be any arbitrary 256 bit value, and there are mechanisms -for advanced users to create derived addresses -(`SystemProgram::CreateAccountWithSeed`, -[`Pubkey::CreateProgramAddress`](calling-between-programs.md#program-derived-addresses)). - -Accounts that have never been created via the system program can also be passed -to programs. When an instruction references an account that hasn't been -previously created, the program will be passed an account with no data and zero lamports -that is owned by the system program. - -Such newly created accounts reflect -whether they sign the transaction, and therefore, can be used as an -authority. Authorities in this context convey to the program that the holder of -the private key associated with the account's public key signed the transaction. -The account's public key may be known to the program or recorded in another -account, signifying some kind of ownership or authority over an asset or -operation the program controls or performs. - -## Ownership and Assignment to Programs - -A created account is initialized to be _owned_ by a built-in program called the -System program and is called a _system account_ aptly. An account includes -"owner" metadata. The owner is a program id. The runtime grants the program -write access to the account if its id matches the owner. For the case of the -System program, the runtime allows clients to transfer lamports and importantly -_assign_ account ownership, meaning changing the owner to a different program id. If -an account is not owned by a program, the program is only permitted to read its -data and credit the account. - -## Verifying validity of unmodified, reference-only accounts - -For security purposes, it is recommended that programs check the validity of any -account it reads, but does not modify. - -This is because a malicious user -could create accounts with arbitrary data and then pass these accounts to the -program in place of valid accounts. The arbitrary data could be crafted in -a way that leads to unexpected or harmful program behavior. - -The security model enforces that an account's data can only be modified by the -account's `Owner` program. This allows the program to trust that the data -is passed to them via accounts they own. The -runtime enforces this by rejecting any transaction containing a program that -attempts to write to an account it does not own. - -If a program were to not check account validity, it might read an account -it thinks it owns, but doesn't. Anyone can -issue instructions to a program, and the runtime does not know that those -accounts are expected to be owned by the program. - -To check an account's validity, the program should either check the account's -address against a known value, or check that the account is indeed owned -correctly (usually owned by the program itself). - -One example is when programs use a sysvar account. Unless the program checks the -account's address or owner, it's impossible to be sure whether it's a real and -valid sysvar account merely by successful deserialization of the account's data. - -Accordingly, the Solana SDK [checks the sysvar account's validity during -deserialization](https://github.com/solana-labs/solana/blob/a95675a7ce1651f7b59443eb146b356bc4b3f374/sdk/program/src/sysvar/mod.rs#L65). -An alternative and safer way to read a sysvar is via the sysvar's [`get()` -function](https://github.com/solana-labs/solana/blob/64bfc14a75671e4ec3fe969ded01a599645080eb/sdk/program/src/sysvar/mod.rs#L73) -which doesn't require these checks. - -If the program always modifies the account in question, the address/owner check -isn't required because modifying an unowned account will be rejected by the runtime, -and the containing transaction will be thrown out. - -## Rent - -Keeping accounts alive on Solana incurs a storage cost called _rent_ because the -blockchain cluster must actively maintain the data to process any future transactions. -This is different from Bitcoin and Ethereum, where storing accounts doesn't -incur any costs. - -Currently, all new accounts are required to be rent-exempt. - -### Rent exemption - -An account is considered rent-exempt if it holds at least 2 years worth of rent. -This is checked every time an account's balance is reduced, and transactions -that would reduce the balance to below the minimum amount will fail. - -Program executable accounts are required by the runtime to be rent-exempt to -avoid being purged. - -:::info -Use the [`getMinimumBalanceForRentExemption`](../../api/http#getminimumbalanceforrentexemption) RPC -endpoint to calculate the -minimum balance for a particular account size. The following calculation is -illustrative only. -::: - -For example, a program executable with the size of 15,000 bytes requires a -balance of 105,290,880 lamports (=~ 0.105 SOL) to be rent-exempt: - -```text -105,290,880 = 19.055441478439427 (fee rate) * (128 + 15_000)(account size including metadata) * ((365.25/2) * 2)(epochs in 2 years) -``` - -Rent can also be estimated via the [`solana rent` CLI subcommand](cli/usage.md#solana-rent) - -```text -$ solana rent 15000 -Rent per byte-year: 0.00000348 SOL -Rent per epoch: 0.000288276 SOL -Rent-exempt minimum: 0.10529088 SOL -``` - -Note: Rest assured that, should the storage rent rate need to be increased at some -point in the future, steps will be taken to ensure that accounts that are rent-exempt -before the increase will remain rent-exempt afterwards diff --git a/docs/src/developing/programming-model/calling-between-programs.md b/docs/src/developing/programming-model/calling-between-programs.md deleted file mode 100644 index 4ed95dba1c..0000000000 --- a/docs/src/developing/programming-model/calling-between-programs.md +++ /dev/null @@ -1,359 +0,0 @@ ---- -title: Calling Between Programs ---- - -## Cross-Program Invocations - -The Solana runtime allows programs to call each other via a mechanism called -cross-program invocation. Calling between programs is achieved by one program -invoking an instruction of the other. The invoking program is halted until the -invoked program finishes processing the instruction. - -For example, a client could create a transaction that modifies two accounts, -each owned by separate on-chain programs: - -```rust,ignore -let message = Message::new(vec![ - token_instruction::pay(&alice_pubkey), - acme_instruction::launch_missiles(&bob_pubkey), -]); -client.send_and_confirm_message(&[&alice_keypair, &bob_keypair], &message); -``` - -A client may instead allow the `acme` program to conveniently invoke `token` -instructions on the client's behalf: - -```rust,ignore -let message = Message::new(vec![ - acme_instruction::pay_and_launch_missiles(&alice_pubkey, &bob_pubkey), -]); -client.send_and_confirm_message(&[&alice_keypair, &bob_keypair], &message); -``` - -Given two on-chain programs, `token` and `acme`, each implementing instructions -`pay()` and `launch_missiles()` respectively, `acme` can be implemented with a -call to a function defined in the `token` module by issuing a cross-program -invocation: - -```rust,ignore -mod acme { - use token_instruction; - - fn launch_missiles(accounts: &[AccountInfo]) -> Result<()> { - ... - } - - fn pay_and_launch_missiles(accounts: &[AccountInfo]) -> Result<()> { - let alice_pubkey = accounts[1].key; - let instruction = token_instruction::pay(&alice_pubkey); - invoke(&instruction, accounts)?; - - launch_missiles(accounts)?; - } -``` - -`invoke()` is built into Solana's runtime and is responsible for routing the -given instruction to the `token` program via the instruction's `program_id` -field. - -Note that `invoke` requires the caller to pass all the accounts required by the -instruction being invoked, except for the executable account (the `program_id`). - -Before invoking `pay()`, the runtime must ensure that `acme` didn't modify any -accounts owned by `token`. It does this by applying the runtime's policy to the -current state of the accounts at the time `acme` calls `invoke` vs. the initial -state of the accounts at the beginning of the `acme`'s instruction. After -`pay()` completes, the runtime must again ensure that `token` didn't modify any -accounts owned by `acme` by again applying the runtime's policy, but this time -with the `token` program ID. Lastly, after `pay_and_launch_missiles()` -completes, the runtime must apply the runtime policy one more time where it -normally would, but using all updated `pre_*` variables. If executing -`pay_and_launch_missiles()` up to `pay()` made no invalid account changes, -`pay()` made no invalid changes, and executing from `pay()` until -`pay_and_launch_missiles()` returns made no invalid changes, then the runtime -can transitively assume `pay_and_launch_missiles()` as a whole made no invalid -account changes, and therefore commit all these account modifications. - -### Instructions that require privileges - -The runtime uses the privileges granted to the caller program to determine what -privileges can be extended to the callee. Privileges in this context refer to -signers and writable accounts. For example, if the instruction the caller is -processing contains a signer or writable account, then the caller can invoke an -instruction that also contains that signer and/or writable account. - -This privilege extension relies on the fact that programs are immutable, except -during the special case of program upgrades. - -In the case of the `acme` program, the runtime can safely treat the transaction's -signature as a signature of a `token` instruction. When the runtime sees the -`token` instruction references `alice_pubkey`, it looks up the key in the `acme` -instruction to see if that key corresponds to a signed account. In this case, it -does and thereby authorizes the `token` program to modify Alice's account. - -### Program signed accounts - -Programs can issue instructions that contain signed accounts that were not -signed in the original transaction by using [Program derived -addresses](#program-derived-addresses). - -To sign an account with program derived addresses, a program may -`invoke_signed()`. - -```rust,ignore - invoke_signed( - &instruction, - accounts, - &[&["First addresses seed"], - &["Second addresses first seed", "Second addresses second seed"]], - )?; -``` - -### Call Depth - -Cross-program invocations allow programs to invoke other programs directly, but -the depth is constrained currently to 4. - -### Reentrancy - -Reentrancy is currently limited to direct self recursion, capped at a fixed -depth. This restriction prevents situations where a program might invoke another -from an intermediary state without the knowledge that it might later be called -back into. Direct recursion gives the program full control of its state at the -point that it gets called back. - -## Program Derived Addresses - -Program derived addresses allow programmatically generated signatures to be used -when [calling between programs](#cross-program-invocations). - -Using a program derived address, a program may be given the authority over an -account and later transfer that authority to another. This is possible because -the program can act as the signer in the transaction that gives authority. - -For example, if two users want to make a wager on the outcome of a game in -Solana, they must each transfer their wager's assets to some intermediary that -will honor their agreement. Currently, there is no way to implement this -intermediary as a program in Solana because the intermediary program cannot -transfer the assets to the winner. - -This capability is necessary for many DeFi applications since they require -assets to be transferred to an escrow agent until some event occurs that -determines the new owner. - -- Decentralized Exchanges that transfer assets between matching bid and ask - orders. - -- Auctions that transfer assets to the winner. - -- Games or prediction markets that collect and redistribute prizes to the - winners. - -Program derived address: - -1. Allow programs to control specific addresses, called program addresses, in - such a way that no external user can generate valid transactions with - signatures for those addresses. - -2. Allow programs to programmatically sign for program addresses that are - present in instructions invoked via [Cross-Program Invocations](#cross-program-invocations). - -Given the two conditions, users can securely transfer or assign the authority of -on-chain assets to program addresses, and the program can then assign that -authority elsewhere at its discretion. - -### Private keys for program addresses - -A program address does not lie on the ed25519 curve and therefore has no valid -private key associated with it, and thus generating a signature for it is -impossible. While it has no private key of its own, it can be used by a program -to issue an instruction that includes the program address as a signer. - -### Hash-based generated program addresses - -Program addresses are deterministically derived from a collection of seeds and a -program id using a 256-bit pre-image resistant hash function. Program address -must not lie on the ed25519 curve to ensure there is no associated private key. -During generation, an error will be returned if the address is found to lie on -the curve. There is about a 50/50 chance of this happening for a given -collection of seeds and program id. If this occurs a different set of seeds or -a seed bump (additional 8 bit seed) can be used to find a valid program address -off the curve. - -Deterministic program addresses for programs follow a similar derivation path as -Accounts created with `SystemInstruction::CreateAccountWithSeed` which is -implemented with `Pubkey::create_with_seed`. - -For reference, that implementation is as follows: - -```rust,ignore -pub fn create_with_seed( - base: &Pubkey, - seed: &str, - program_id: &Pubkey, -) -> Result { - if seed.len() > MAX_ADDRESS_SEED_LEN { - return Err(SystemError::MaxSeedLengthExceeded); - } - - Ok(Pubkey::new( - hashv(&[base.as_ref(), seed.as_ref(), program_id.as_ref()]).as_ref(), - )) -} -``` - -Programs can deterministically derive any number of addresses by using seeds. -These seeds can symbolically identify how the addresses are used. - -From `Pubkey`:: - -```rust,ignore -/// Generate a derived program address -/// * seeds, symbolic keywords used to derive the key -/// * program_id, program that the address is derived for -pub fn create_program_address( - seeds: &[&[u8]], - program_id: &Pubkey, -) -> Result - -/// Find a valid off-curve derived program address and its bump seed -/// * seeds, symbolic keywords used to derive the key -/// * program_id, program that the address is derived for -pub fn find_program_address( - seeds: &[&[u8]], - program_id: &Pubkey, -) -> Option<(Pubkey, u8)> { - let mut bump_seed = [std::u8::MAX]; - for _ in 0..std::u8::MAX { - let mut seeds_with_bump = seeds.to_vec(); - seeds_with_bump.push(&bump_seed); - if let Ok(address) = create_program_address(&seeds_with_bump, program_id) { - return Some((address, bump_seed[0])); - } - bump_seed[0] -= 1; - } - None -} -``` - - **Warning**: Because of the way the seeds are hashed there is a potential for - program address collisions for the same program id. The seeds are hashed - sequentially which means that seeds {"abcdef"}, {"abc", "def"}, and {"ab", - "cd", "ef"} will all result in the same program address given the same program - id. Since the chance of collision is local to a given program id, the developer - of that program must take care to choose seeds that do not collide with each - other. For seed schemes that are susceptible to this type of hash collision, a - common remedy is to insert separators between seeds, e.g. transforming {"abc", - "def"} into {"abc", "-", "def"}. - -### Using program addresses - -Clients can use the `create_program_address` function to generate a destination -address. In this example, we assume that -`create_program_address(&[&["escrow"]], &escrow_program_id)` generates a valid -program address that is off the curve. - -```rust,ignore -// deterministically derive the escrow key -let escrow_pubkey = create_program_address(&[&["escrow"]], &escrow_program_id); - -// construct a transfer message using that key -let message = Message::new(vec![ - token_instruction::transfer(&alice_pubkey, &escrow_pubkey, 1), -]); - -// process the message which transfer one 1 token to the escrow -client.send_and_confirm_message(&[&alice_keypair], &message); -``` - -Programs can use the same function to generate the same address. In the function -below the program issues a `token_instruction::transfer` from a program address -as if it had the private key to sign the transaction. - -```rust,ignore -fn transfer_one_token_from_escrow( - program_id: &Pubkey, - accounts: &[AccountInfo], -) -> ProgramResult { - // User supplies the destination - let alice_pubkey = keyed_accounts[1].unsigned_key(); - - // Deterministically derive the escrow pubkey. - let escrow_pubkey = create_program_address(&[&["escrow"]], program_id); - - // Create the transfer instruction - let instruction = token_instruction::transfer(&escrow_pubkey, &alice_pubkey, 1); - - // The runtime deterministically derives the key from the currently - // executing program ID and the supplied keywords. - // If the derived address matches a key marked as signed in the instruction - // then that key is accepted as signed. - invoke_signed(&instruction, accounts, &[&["escrow"]]) -} -``` - -Note that the address generated using `create_program_address` is not guaranteed -to be a valid program address off the curve. For example, let's assume that the -seed `"escrow2"` does not generate a valid program address. - -To generate a valid program address using `"escrow2"` as a seed, use -`find_program_address`, iterating through possible bump seeds until a valid -combination is found. The preceding example becomes: - -```rust,ignore -// find the escrow key and valid bump seed -let (escrow_pubkey2, escrow_bump_seed) = find_program_address(&[&["escrow2"]], &escrow_program_id); - -// construct a transfer message using that key -let message = Message::new(vec![ - token_instruction::transfer(&alice_pubkey, &escrow_pubkey2, 1), -]); - -// process the message which transfer one 1 token to the escrow -client.send_and_confirm_message(&[&alice_keypair], &message); -``` - -Within the program, this becomes: - -```rust,ignore -fn transfer_one_token_from_escrow2( - program_id: &Pubkey, - accounts: &[AccountInfo], -) -> ProgramResult { - // User supplies the destination - let alice_pubkey = keyed_accounts[1].unsigned_key(); - - // Iteratively derive the escrow pubkey - let (escrow_pubkey2, bump_seed) = find_program_address(&[&["escrow2"]], program_id); - - // Create the transfer instruction - let instruction = token_instruction::transfer(&escrow_pubkey2, &alice_pubkey, 1); - - // Include the generated bump seed to the list of all seeds - invoke_signed(&instruction, accounts, &[&["escrow2", &[bump_seed]]]) -} -``` - -Since `find_program_address` requires iterating over a number of calls to -`create_program_address`, it may use more -[compute budget](developing/programming-model/runtime.md#compute-budget) when -used on-chain. To reduce the compute cost, use `find_program_address` off-chain -and pass the resulting bump seed to the program. - -### Instructions that require signers - -The addresses generated with `create_program_address` and `find_program_address` -are indistinguishable from any other public key. The only way for the runtime to -verify that the address belongs to a program is for the program to supply the -seeds used to generate the address. - -The runtime will internally call `create_program_address`, and compare the -result against the addresses supplied in the instruction. - -## Examples - -Refer to [Developing with -Rust](developing/on-chain-programs/../../../on-chain-programs/developing-rust.md#examples) -and [Developing with -C](developing/on-chain-programs/../../../on-chain-programs/developing-c.md#examples) -for examples of how to use cross-program invocation. diff --git a/docs/src/developing/programming-model/overview.md b/docs/src/developing/programming-model/overview.md deleted file mode 100644 index 43375b5292..0000000000 --- a/docs/src/developing/programming-model/overview.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: "Overview" ---- - -An [app](terminology.md#app) interacts with a Solana cluster by sending it -[transactions](transactions.md) with one or more -[instructions](transactions.md#instructions). The Solana [runtime](runtime.md) -passes those instructions to [programs](terminology.md#program) deployed by app -developers beforehand. An instruction might, for example, tell a program to -transfer [lamports](terminology.md#lamport) from one [account](accounts.md) to -another or create an interactive contract that governs how lamports are -transferred. Instructions are executed sequentially and atomically for each -transaction. If any instruction is invalid, all account changes in the -transaction are discarded. - -To start developing immediately you can build, deploy, and run one of the -[examples](developing/on-chain-programs/examples.md). diff --git a/docs/src/developing/programming-model/runtime.md b/docs/src/developing/programming-model/runtime.md deleted file mode 100644 index ab95bef8dd..0000000000 --- a/docs/src/developing/programming-model/runtime.md +++ /dev/null @@ -1,172 +0,0 @@ ---- -title: "Runtime" ---- - -## Capability of Programs - -The runtime only permits the owner program to debit the account or modify its -data. The program then defines additional rules for whether the client can -modify accounts it owns. In the case of the System program, it allows users to -transfer lamports by recognizing transaction signatures. If it sees the client -signed the transaction using the keypair's _private key_, it knows the client -authorized the token transfer. - -In other words, the entire set of accounts owned by a given program can be -regarded as a key-value store, where a key is the account address and value is -program-specific arbitrary binary data. A program author can decide how to -manage the program's whole state, possibly as many accounts. - -After the runtime executes each of the transaction's instructions, it uses the -account metadata to verify that the access policy was not violated. If a program -violates the policy, the runtime discards all account changes made by all -instructions in the transaction, and marks the transaction as failed. - -### Policy - -After a program has processed an instruction, the runtime verifies that the -program only performed operations it was permitted to, and that the results -adhere to the runtime policy. - -The policy is as follows: - -- Only the owner of the account may change owner. - - And only if the account is writable. - - And only if the account is not executable. - - And only if the data is zero-initialized or empty. -- An account not assigned to the program cannot have its balance decrease. -- The balance of read-only and executable accounts may not change. -- Only the owner may change account size and data. - - And if the account is writable. - - And if the account is not executable. -- Executable is one-way (false->true) and only the account owner may set it. -- No one can make modifications to the rent_epoch associated with this account. - -## Balancing the balances - -Before and after each instruction, the sum of all account balances must stay the same. -E.g. if one account's balance is increased, another's must be decreased by the same amount. -Because the runtime can not see changes to accounts which were not passed to it, -all accounts for which the balances were modified must be passed, -even if they are not needed in the called instruction. - -## Compute Budget - -To prevent abuse of computational resources, each transaction is allocated a -compute budget. The budget specifies a maximum number of compute units that a -transaction can consume, the costs associated with different types of operations -the transaction may perform, and operational bounds the transaction must adhere -to. - -As the transaction is processed compute units are consumed by its -instruction's programs performing operations such as executing SBF instructions, -calling syscalls, etc... When the transaction consumes its entire budget, or -exceeds a bound such as attempting a call stack that is too deep, or loaded -account data size exceeds limit, the runtime halts the transaction processing and -returns an error. - -The following operations incur a compute cost: - -- Executing SBF instructions -- Passing data between programs -- Calling system calls - - logging - - creating program addresses - - cross-program invocations - - ... - -For cross-program invocations, the instructions invoked inherit the budget of -their parent. If an invoked instruction consumes the transactions remaining -budget, or exceeds a bound, the entire invocation chain and the top level -transaction processing are halted. - -The current [compute -budget](https://github.com/solana-labs/solana/blob/090e11210aa7222d8295610a6ccac4acda711bb9/program-runtime/src/compute_budget.rs#L26-L87) can be found in the Solana Program Runtime. - -#### Example Compute Budget - -For example, if the compute budget set in the Solana runtime is: - -```rust -max_units: 1,400,000, -log_u64_units: 100, -create_program address units: 1500, -invoke_units: 1000, -max_invoke_stack_height: 5, -max_instruction_trace_length: 64, -max_call_depth: 64, -stack_frame_size: 4096, -log_pubkey_units: 100, -... -``` - -Then any transaction: - -- Could execute 1,400,000 SBF instructions, if it did nothing else. -- Cannot exceed 4k of stack usage. -- Cannot exceed a SBF call depth of 64. -- Cannot exceed invoke stack height of 5 (4 levels of cross-program invocations). - -> **NOTE:** Since the compute budget is consumed incrementally as the transaction executes, -> the total budget consumption will be a combination of the various costs of the -> operations it performs. - -At runtime a program may log how much of the compute budget remains. See -[debugging](developing/on-chain-programs/debugging.md#monitoring-compute-budget-consumption) -for more information. - -### Prioritization fees - -As part of the Compute Budget, the runtime supports transactions including an -**optional** fee to prioritize itself against others known as a -[prioritization fee](./../../transaction_fees.md#prioritization-fee). - -This _prioritization fee_ is calculated by multiplying the number -of _compute units_ by the _compute unit price_ (measured in micro-lamports). -These values may be set via the Compute Budget instructions `SetComputeUnitLimit` -and `SetComputeUnitPrice` once per transaction. - -:::info -You can learn more of the specifics of _how_ and _when_ to set a prioritization fee -on the [transaction fees](./../../transaction_fees.md#prioritization-fee) page. -::: - -### Accounts data size limit - -A transaction should request the maximum bytes of accounts data it is -allowed to load by including a `SetLoadedAccountsDataSizeLimit` instruction, requested -limit is capped by `MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES`. If no -`SetLoadedAccountsDataSizeLimit` is provided, the transaction is defaulted to -have limit of `MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES`. - -The `ComputeBudgetInstruction::set_loaded_accounts_data_size_limit` function can be used -to create this instruction: - -```rust -let instruction = ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(100_000); -``` - -## New Features - -As Solana evolves, new features or patches may be introduced that changes the -behavior of the cluster and how programs run. Changes in behavior must be -coordinated between the various nodes of the cluster. If nodes do not -coordinate, then these changes can result in a break-down of consensus. Solana -supports a mechanism called runtime features to facilitate the smooth adoption -of changes. - -Runtime features are epoch coordinated events where one or more behavior changes -to the cluster will occur. New changes to Solana that will change behavior are -wrapped with feature gates and disabled by default. The Solana tools are then -used to activate a feature, which marks it pending, once marked pending the -feature will be activated at the next epoch. - -To determine which features are activated use the [Solana command-line -tools](cli/install-solana-cli-tools.md): - -```bash -solana feature status -``` - -If you encounter problems, first ensure that the Solana tools version you are -using match the version returned by `solana cluster-version`. If they do not -match, [install the correct tool suite](cli/install-solana-cli-tools.md). diff --git a/docs/src/developing/programming-model/transactions.md b/docs/src/developing/programming-model/transactions.md deleted file mode 100644 index 1f88d4117b..0000000000 --- a/docs/src/developing/programming-model/transactions.md +++ /dev/null @@ -1,224 +0,0 @@ ---- -title: "Transactions" -description: "A Solana transaction consists of one or more instructions, an array of accounts to read and write data from, and one or more signatures." ---- - -On the Solana blockchain, program execution begins with a [transaction](./../../terminology.md#transaction) being submitted to the cluster. With each transaction consisting of one or many [instructions](./../../terminology.md#instruction), the runtime will process each of the instructions contained within the transaction, in order, and atomically. If any part of an instruction fails, then the entire transaction will fail. - -## Overview of a Transaction - -On Solana, clients update the runtime (for example, debiting an account) by submitting a transaction to the cluster. - -This transaction consists of three parts: - -- one or more instructions -- an array of accounts to read or write from -- one or more signatures - -An [instruction](./../../terminology.md#instruction) is the smallest execution logic on Solana. Instructions are basically a call to update the global Solana state. Instructions invoke programs that make calls to the Solana runtime to update the state (for example, calling the token program to transfer tokens from your account to another account). - -[Programs](./../intro/programs.md) on Solana don’t store data/state; rather, data/state is stored in accounts. - -[Signatures](./../../terminology.md#signature) verify that we have the authority to read or write data to the accounts that we list. - -## Anatomy of a Transaction - -This section covers the binary format of a transaction. - -### Transaction Format - -A transaction contains a [compact-array](#compact-array-format) of signatures, -followed by a [message](#message-format). Each item in the signatures array is -a [digital signature](#signature-format) of the given message. The Solana -runtime verifies that the number of signatures matches the number in the first -8 bits of the [message header](#message-header-format). It also verifies that -each signature was signed by the private key corresponding to the public key at -the same index in the message's account addresses array. - -#### Signature Format - -Each digital signature is in the ed25519 binary format and consumes 64 bytes. - -### Message Format - -A message contains a [header](#message-header-format), followed by a -compact-array of [account addresses](#account-addresses-format), followed by a -recent [blockhash](#blockhash-format), followed by a compact-array of -[instructions](#instruction-format). - -#### Message Header Format - -The message header contains three unsigned 8-bit values. The first value is the -number of required signatures in the containing transaction. The second value -is the number of those corresponding account addresses that are read-only. The -third value in the message header is the number of read-only account addresses -not requiring signatures. - -#### Account Addresses Format - -The addresses that require signatures appear at the beginning of the account -address array, with addresses requesting read-write access first, and read-only -accounts following. The addresses that do not require signatures follow the -addresses that do, again with read-write accounts first and read-only accounts -following. - -#### Blockhash Format - -A blockhash contains a 32-byte SHA-256 hash. It is used to indicate when a -client last observed the ledger. Validators will reject transactions when the -blockhash is too old. - -### Instruction Format - -An instruction contains a program id index, followed by a compact-array of -account address indexes, followed by a compact-array of opaque 8-bit data. The -program id index is used to identify an on-chain program that can interpret the -opaque data. The program id index is an unsigned 8-bit index to an account -address in the message's array of account addresses. The account address -indexes are each an unsigned 8-bit index into that same array. - -### Compact-Array Format - -A compact-array is serialized as the array length, followed by each array item. -The array length is a special multi-byte encoding called compact-u16. - -#### Compact-u16 Format - -A compact-u16 is a multi-byte encoding of 16 bits. The first byte contains the -lower 7 bits of the value in its lower 7 bits. If the value is above 0x7f, the -high bit is set and the next 7 bits of the value are placed into the lower 7 -bits of a second byte. If the value is above 0x3fff, the high bit is set and -the remaining 2 bits of the value are placed into the lower 2 bits of a third -byte. - -### Account Address Format - -An account address is 32-bytes of arbitrary data. When the address requires a -digital signature, the runtime interprets it as the public key of an ed25519 -keypair. - -## Instructions - -Each [instruction](terminology.md#instruction) specifies a single program, a -subset of the transaction's accounts that should be passed to the program, and a -data byte array that is passed to the program. The program interprets the data -array and operates on the accounts specified by the instructions. The program -can return successfully, or with an error code. An error return causes the -entire transaction to fail immediately. - -Programs typically provide helper functions to construct instructions they -support. For example, the system program provides the following Rust helper to -construct a -[`SystemInstruction::CreateAccount`](https://github.com/solana-labs/solana/blob/6606590b8132e56dab9e60b3f7d20ba7412a736c/sdk/program/src/system_instruction.rs#L63) -instruction: - -```rust -pub fn create_account( - from_pubkey: &Pubkey, - to_pubkey: &Pubkey, - lamports: u64, - space: u64, - owner: &Pubkey, -) -> Instruction { - let account_metas = vec![ - AccountMeta::new(*from_pubkey, true), - AccountMeta::new(*to_pubkey, true), - ]; - Instruction::new_with_bincode( - system_program::id(), - &SystemInstruction::CreateAccount { - lamports, - space, - owner: *owner, - }, - account_metas, - ) -} -``` - -Which can be found here: - -https://github.com/solana-labs/solana/blob/6606590b8132e56dab9e60b3f7d20ba7412a736c/sdk/program/src/system_instruction.rs#L220 - -### Program Id - -The instruction's [program id](./../../terminology.md#program-id) specifies which -program will process this instruction. The program's account's owner specifies -which loader should be used to load and execute the program, and the data -contains information about how the runtime should execute the program. - -In the case of [on-chain SBF programs](./../on-chain-programs/overview.md), -the owner is the SBF Loader and the account data holds the BPF bytecode. Program -accounts are permanently marked as executable by the loader once they are -successfully deployed. The runtime will reject transactions that specify programs -that are not executable. - -Unlike on-chain programs, [Native Programs](../runtime-facilities/programs.md) -are handled differently in that they are built directly into the Solana runtime. - -### Accounts - -The accounts referenced by an instruction represent on-chain state and serve as -both the inputs and outputs of a program. More information about accounts can be -found in the [Accounts](./accounts.md) section. - -### Instruction data - -Each instruction carries a general purpose byte array that is passed to the -program along with the accounts. The contents of the instruction data is program -specific and typically used to convey what operations the program should -perform, and any additional information those operations may need above and -beyond what the accounts contain. - -Programs are free to specify how information is encoded into the instruction -data byte array. The choice of how data is encoded should consider the -overhead of decoding, since that step is performed by the program on-chain. It's -been observed that some common encodings (Rust's bincode for example) are very -inefficient. - -The [Solana Program Library's Token -program](https://github.com/solana-labs/solana-program-library/tree/master/token) -gives one example of how instruction data can be encoded efficiently, but note -that this method only supports fixed sized types. Token utilizes the -[Pack](https://github.com/solana-labs/solana/blob/master/sdk/program/src/program_pack.rs) -trait to encode/decode instruction data for both token instructions as well as -token account states. - -### Multiple instructions in a single transaction - -A transaction can contain instructions in any order. This means a malicious -user could craft transactions that may pose instructions in an order that the -program has not been protected against. Programs should be hardened to properly -and safely handle any possible instruction sequence. - -One not so obvious example is account deinitialization. Some programs may -attempt to deinitialize an account by setting its lamports to zero, with the -assumption that the runtime will delete the account. This assumption may be -valid between transactions, but it is not between instructions or cross-program -invocations. To harden against this, the program should also explicitly zero out the -account's data. - -An example of where this could be a problem is if a token program, upon -transferring the token out of an account, sets the account's lamports to zero, -assuming it will be deleted by the runtime. If the program does not zero out the -account's data, a malicious user could trail this instruction with another that -transfers the tokens a second time. - -## Signatures - -Each transaction explicitly lists all account public keys referenced by the -transaction's instructions. A subset of those public keys are each accompanied -by a transaction signature. Those signatures signal on-chain programs that the -account holder has authorized the transaction. Typically, the program uses the -authorization to permit debiting the account or modifying its data. More -information about how the authorization is communicated to a program can be -found in [Accounts](./accounts.md#signers) - -## Recent Blockhash - -A transaction includes a recent [blockhash](../../terminology.md#blockhash) to prevent -duplication and to give transactions lifetimes. Any transaction that is -completely identical to a previous one is rejected, so adding a newer blockhash -allows multiple transactions to repeat the exact same action. Transactions also -have lifetimes that are defined by the blockhash, as any transaction whose -blockhash is too old will be rejected. diff --git a/docs/src/developing/transaction_confirmation.md b/docs/src/developing/transaction_confirmation.md deleted file mode 100644 index caed1005d7..0000000000 --- a/docs/src/developing/transaction_confirmation.md +++ /dev/null @@ -1,197 +0,0 @@ ---- -title: "Transaction Confirmation" ---- - -Problems relating to [transaction confirmation](./../terminology.md#transaction-confirmations) are common with many newer developers while building applications. This article aims to boost the overall understanding of the confirmation mechanism used on the Solana blockchain, including some recommended best practices. - -## Brief background on transactions - -Let’s first make sure we’re all on the same page and thinking about the same things... - -### What is a transaction? - -Transactions consist of two components: a [message](./../terminology.md#message) and a [list of signatures](./../terminology.md#signature). The transaction message is where the magic happens and at a high level it consists of three components: - -- a **list of instructions** to invoke, -- a **list of accounts** to load, and -- a **“recent blockhash.”** - -In this article, we’re going to be focusing a lot on a transaction’s [recent blockhash](./../terminology.md#blockhash) because it plays a big role in transaction confirmation. - -### Transaction lifecycle refresher - -Below is a high level view of the lifecycle of a transaction. This article will touch on everything except steps 1 and 4. - -1. Create a list of instructions along with the list of accounts that instructions need to read and write -2. Fetch a recent blockhash and use it to prepare a transaction message -3. Simulate the transaction to ensure it behaves as expected -4. Prompt user to sign the prepared transaction message with their private key -5. Send the transaction to an RPC node which attempts to forward it to the current block producer -6. Hope that a block producer validates and commits the transaction into their produced block -7. Confirm the transaction has either been included in a block or detect when it has expired - -## What is a Blockhash? - -A [“blockhash”](./../terminology.md#blockhash) refers to the last Proof of History (PoH) hash for a [“slot”](./../terminology.md#slot) (description below). Since Solana uses PoH as a trusted clock, a transaction’s recent blockhash can be thought of as a **timestamp**. - -### Proof of History refresher - -Solana’s Proof of History mechanism uses a very long chain of recursive SHA-256 hashes to build a trusted clock. The “history” part of the name comes from the fact that block producers hash transaction id’s into the stream to record which transactions were processed in their block. - -[PoH hash calculation](https://github.com/solana-labs/solana/blob/9488a73f5252ad0d7ea830a0b456d9aa4bfbb7c1/entry/src/poh.rs#L82): `next_hash = hash(prev_hash, hash(transaction_ids))` - -PoH can be used as a trusted clock because each hash must be produced sequentially. Each produced block contains a blockhash and a list of hash checkpoints called “ticks” so that validators can verify the full chain of hashes in parallel and prove that some amount of time has actually passed. The stream of hashes can be broken up into the following time units: - -# Transaction Expiration - -By default, all Solana transactions will expire if not committed to a block in a certain amount of time. The **vast majority** of transaction confirmation issues are related to how RPC nodes and validators detect and handle **expired** transactions. A solid understanding of how transaction expiration works should help you diagnose the bulk of your transaction confirmation issues. - -## How does transaction expiration work? - -Each transaction includes a “recent blockhash” which is used as a PoH clock timestamp and expires when that blockhash is no longer “recent” enough. More concretely, Solana validators look up the corresponding slot number for each transaction’s blockhash that they wish to process in a block. If the validator [can’t find a slot number for the blockhash](https://github.com/solana-labs/solana/blob/9488a73f5252ad0d7ea830a0b456d9aa4bfbb7c1/runtime/src/bank.rs#L3687) or if the looked up slot number is more than 151 slots lower than the slot number of the block being processed, the transaction will be rejected. - -Slots are configured to last about [400ms](https://github.com/solana-labs/solana/blob/47b938e617b77eb3fc171f19aae62222503098d7/sdk/program/src/clock.rs#L12) but often fluctuate between 400ms and 600ms, so a given blockhash can only be used by transactions for about 60 to 90 seconds. - -Transaction has expired pseudocode: `currentBankSlot > slotForTxRecentBlockhash + 151` - -Transaction not expired pseudocode: `currentBankSlot - slotForTxRecentBlockhash < 152` - -### Example of transaction expiration - -Let’s walk through a quick example: - -1. A validator is producing a new block for slot #1000 -2. The validator receives a transaction with recent blockhash `1234...` from a user -3. The validator checks the `1234...` blockhash against the list of recent blockhashes leading up to its new block and discovers that it was the blockhash for slot #849 -4. Since slot #849 is exactly 151 slots lower than slot #1000, the transaction hasn’t expired yet and can still be processed! -5. But wait, before actually processing the transaction, the validator finished the block for slot #1000 and starts producing the block for slot #1001 (validators get to produce blocks for 4 consecutive slots). -6. The validator checks the same transaction again and finds that it’s now too old and drops it because it’s now 152 slots lower than the current slot :( - -## Why do transactions expire? - -There’s a very good reason for this actually, it’s to help validators avoid processing the same transaction twice. - -A naive brute force approach to prevent double processing could be to check every new transaction against the blockchain’s entire transaction history. But by having transactions expire after a short amount of time, validators only need to check if a new transaction is in a relatively small set of _recently_ processed transactions. - -### Other blockchains - -Solana’s approach of prevent double processing is quite different from other blockchains. For example, Ethereum tracks a counter (nonce) for each transaction sender and will only process transactions that use the next valid nonce. - -Ethereum’s approach is simple for validators to implement, but it can be problematic for users. Many people have encountered situations when their Ethereum transactions got stuck in a _pending_ state for a long time and all the later transactions, which used higher nonce values, were blocked from processing. - -### Advantages on Solana - -There are a few advantages to Solana’s approach: - -1. A single fee payer can submit multiple transactions at the same time that are allowed to be processed in any order. This might happen if you’re using multiple applications at the same time. -2. If a transaction doesn’t get committed to a block and expires, users can try again knowing that their previous transaction won’t ever be processed. - -By not using counters, the Solana wallet experience may be easier for users to understand because they can get to success, failure, or expiration states quickly and avoid annoying pending states. - -### Disadvantages on Solana - -Of course there are some disadvantages too: - -1. Validators have to actively track a set of all processed transaction id’s to prevent double processing. -2. If the expiration time period is too short, users might not be able to submit their transaction before it expires. - -These disadvantages highlight a tradeoff in how transaction expiration is configured. If the expiration time of a transaction is increased, validators need to use more memory to track more transactions. If expiration time is decreased, users don’t have enough time to submit their transaction. - -Currently, Solana clusters require that transactions use blockhashes that are no more than [151 slots](https://github.com/solana-labs/solana/blob/9488a73f5252ad0d7ea830a0b456d9aa4bfbb7c1/sdk/program/src/clock.rs#L65) old. - -> This [Github issue](https://github.com/solana-labs/solana/issues/23582) contains some calculations that estimate that mainnet-beta validators need about 150MB of memory to track transactions. -> This could be slimmed down in the future if necessary without decreasing expiration time as I’ve detailed in that issue. - -## Transaction confirmation tips - -As mentioned before, blockhashes expire after a time period of only 151 slots which can pass as quickly as **one minute** when slots are processed within the target time of 400ms. - -One minute is not a lot of time considering that a client needs to fetch a recent blockhash, wait for the user to sign, and finally hope that the broadcasted transaction reaches a leader that is willing to accept it. Let’s go through some tips to help avoid confirmation failures due to transaction expiration! - -### Fetch blockhashes with the appropriate commitment level - -Given the short expiration time frame, it’s imperative that clients help users create transactions with blockhash that is as recent as possible. - -When fetching blockhashes, the current recommended RPC API is called [`getLatestBlockhash`](/api/http#getlatestblockhash). By default, this API uses the `"finalized"` commitment level to return the most recently finalized block’s blockhash. However, you can override this behavior by [setting the `commitment` parameter](/api/http#configuring-state-commitment) to a different commitment level. - -**Recommendation** - -The `"confirmed"` commitment level should almost always be used for RPC requests because it’s usually only a few slots behind the `"processed"` commitment and has a very low chance of belonging to a dropped [fork](./../cluster/fork-generation.md). - -But feel free to consider the other options: - -- Choosing `"processed"` will let you fetch the most recent blockhash compared to other commitment levels and therefore gives you the most time to prepare and process a transaction. But due to the prevalence of forking in the Solana protocol, roughly 5% of blocks don’t end up being finalized by the cluster so there’s a real chance that your transaction uses a blockhash that belongs to a dropped fork. Transactions that use blockhashes for abandoned blocks won’t ever be considered recent by any blocks that are in the finalized blockchain. -- Using the default commitment level `"finalized"` will eliminate any risk that the blockhash you choose will belong to a dropped fork. The tradeoff is that there is typically at least a 32 slot difference between the most recent confirmed block and the most recent finalized block. This tradeoff is pretty severe and effectively reduces the expiration of your transactions by about 13 seconds but this could be even more during unstable cluster conditions. - -### Use an appropriate preflight commitment level - -If your transaction uses a blockhash that was fetched from one RPC node then you send, or simulate, that transaction with a different RPC node, you could run into issues due to one node lagging behind the other. - -When RPC nodes receive a `sendTransaction` request, they will attempt to determine the expiration block of your transaction using the most recent finalized block or with the block selected by the `preflightCommitment` parameter. A **VERY** common issue is that a received transaction’s blockhash was produced after the block used to calculate the expiration for that transaction. If an RPC node can’t determine when your transaction expires, it will only forward your transaction **one time** and then will **drop** the transaction. - -Similarly, when RPC nodes receive a `simulateTransaction` request, they will simulate your transaction using the most recent finalized block or with the block selected by the `preflightCommitment` parameter. If the block chosen for simulation is older than the block used for your transaction’s blockhash, the simulation will fail with the dreaded “blockhash not found” error. - -**Recommendation** - -Even if you use `skipPreflight`, **ALWAYS** set the `preflightCommitment` parameter to the same commitment level used to fetch your transaction’s blockhash for both `sendTransaction` and `simulateTransaction` requests. - -### Be wary of lagging RPC nodes when sending transactions - -When your application uses an RPC pool service or when the RPC endpoint differs between creating a transaction and sending a transaction, you need to be wary of situations where one RPC node is lagging behind the other. For example, if you fetch a transaction blockhash from one RPC node then you send that transaction to a second RPC node for forwarding or simulation, the second RPC node might be lagging behind the first. - -**Recommendation** - -For `sendTransaction` requests, clients should keep resending a transaction to a RPC node on a frequent interval so that if an RPC node is slightly lagging behind the cluster, it will eventually catch up and detect your transaction’s expiration properly. - -For `simulateTransaction` requests, clients should use the [`replaceRecentBlockhash`](/api/http#simulatetransaction) parameter to tell the RPC node to replace the simulated transaction’s blockhash with a blockhash that will always be valid for simulation. - -### Avoid reusing stale blockhashes - -Even if your application has fetched a very recent blockhash, be sure that you’re not reusing that blockhash in transactions for too long. The ideal scenario is that a recent blockhash is fetched right before a user signs their transaction. - -**Recommendation for applications** - -Poll for new recent blockhashes on a frequent basis to ensure that whenever a user triggers an action that creates a transaction, your application already has a fresh blockhash that’s ready to go. - -**Recommendation for wallets** - -Poll for new recent blockhashes on a frequent basis and replace a transaction’s recent blockhash right before they sign the transaction to ensure the blockhash is as fresh as possible. - -### Use healthy RPC nodes when fetching blockhashes - -By fetching the latest blockhash with the `"confirmed"` commitment level from an RPC node, it’s going to respond with the blockhash for the latest confirmed block that it’s aware of. Solana’s block propagation protocol prioritizes sending blocks to staked nodes so RPC nodes naturally lag about a block behind the rest of the cluster. They also have to do more work to handle application requests and can lag a lot more under heavy user traffic. - -Lagging RPC nodes can therefore respond to blockhash requests with blockhashes that were confirmed by the cluster quite awhile ago. By default, a lagging RPC node detects that it is more than 150 slots behind the cluster will stop responding to requests, but just before hitting that threshold they can still return a blockhash that is just about to expire. - -**Recommendation** - -Monitor the health of your RPC nodes to ensure that they have an up-to-date view of the cluster state with one of the following methods: - -1. Fetch your RPC node’s highest processed slot by using the [`getSlot`](/api/http#getslot) RPC API with the `"processed"` commitment level and then call the [`getMaxShredInsertSlot](/api/http#getmaxshredinsertslot) RPC API to get the highest slot that your RPC node has received a “shred” of a block for. If the difference between these responses is very large, the cluster is producing blocks far ahead of what the RPC node has processed. -2. Call the `getLatestBlockhash` RPC API with the `"confirmed"` commitment level on a few different RPC API nodes and use the blockhash from the node that returns the highest slot for its [context slot](/api/http#rpcresponse-structure). - -### Wait long enough for expiration - -**Recommendation** - -When calling [`getLatestBlockhash`](/api/http#getlatestblockhash) RPC API to get a recent blockhash for your transaction, take note of the `"lastValidBlockHeight"` in the response. - -Then, poll the [`getBlockHeight`](/api/http#getblockheight) RPC API with the “confirmed” commitment level until it returns a block height greater than the previously returned last valid block height. - -### Consider using “durable” transactions - -Sometimes transaction expiration issues are really hard to avoid (e.g. offline signing, cluster instability). If the previous tips are still not sufficient for your use-case, you can switch to using durable transactions (they just require a bit of setup). - -To start using durable transactions, a user first needs to submit a transaction that [invokes instructions that create a special on-chain “nonce” account](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.create_nonce_account.html) and stores a “durable blockhash” inside of it. At any point in the future (as long as the nonce account hasn’t been used yet), the user can create a durable transaction by following these 2 rules: - -1. The instruction list must start with an [“advance nonce” system instruction](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.advance_nonce_account.html) which loads their on-chain nonce account -2. The transaction’s blockhash must be equal to the durable blockhash stored by the on-chain nonce account - -Here’s how these transactions are processed by the Solana runtime: - -1. If the transaction’s blockhash is no longer “recent”, the runtime checks if the transaction’s instruction list begins with an “advance nonce” system instruction -2. If so, it then loads the nonce account specified by the “advance nonce” instruction -3. Then it checks that the stored durable blockhash matches the transaction’s blockhash -4. Lastly it makes sure to advance the nonce account’s stored blockhash to the latest recent blockhash to ensure that the same transaction can never be processed again - -For more details about how these durable transactions work, you can read the [original proposal](./../implemented-proposals/durable-tx-nonces.md) and [check out an example](./clients/javascript-reference#nonceaccount) in the Solana docs. diff --git a/docs/src/developing/versioned-transactions.md b/docs/src/developing/versioned-transactions.md deleted file mode 100644 index 8d942814d7..0000000000 --- a/docs/src/developing/versioned-transactions.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: Versioned Transactions -description: "" ---- - -[Versioned Transactions](./versioned-transactions.md) are the new transaction format that allow for additional functionality in the Solana runtime, including [Address Lookup Tables](./lookup-tables.md). - -While changes to [on chain](./on-chain-programs/overview.md) programs are **NOT** required to support the new functionality of versioned transactions (or for backwards compatibility), developers **WILL** need update their client side code to prevent [errors due to different transaction versions](#max-supported-transaction-version). - -## Current Transaction Versions - -The Solana runtime supports two transaction versions: - -- `legacy` - older transaction format with no additional benefit -- `0` - added support for [Address Lookup Tables](./lookup-tables.md) - -## Max supported transaction version - -All RPC requests that return a transaction **_should_** specify the highest version of transactions they will support in their application using the `maxSupportedTransactionVersion` option, including [`getBlock`](../api/http#getblock) and [`getTransaction`](../api/http#gettransaction). - -An RPC request will fail if a [Versioned Transaction](./versioned-transactions.md) is returned that is higher than the set `maxSupportedTransactionVersion`. (i.e. if a version `0` transaction is returned when `legacy` is selected) - -> WARNING: -> If no `maxSupportedTransactionVersion` value is set, then only `legacy` transactions will be allowed in the RPC response. Therefore, your RPC requests **WILL** fail if any version `0` transactions are returned. - -## How to set max supported version - -You can set the `maxSupportedTransactionVersion` using both the [`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/) library and JSON formatted requests directly to an RPC endpoint. - -### Using web3.js - -Using the [`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/) library, you can retrieve the most recent block or get a specific transaction: - -```js -// connect to the `devnet` cluster and get the current `slot` -const connection = new web3.Connection(web3.clusterApiUrl("devnet")); -const slot = await connection.getSlot(); - -// get the latest block (allowing for v0 transactions) -const block = await connection.getBlock(slot, { - maxSupportedTransactionVersion: 0, -}); - -// get a specific transaction (allowing for v0 transactions) -const getTx = await connection.getTransaction( - "3jpoANiFeVGisWRY5UP648xRXs3iQasCHABPWRWnoEjeA93nc79WrnGgpgazjq4K9m8g2NJoyKoWBV1Kx5VmtwHQ", - { - maxSupportedTransactionVersion: 0, - }, -); -``` - -### JSON requests to the RPC - -Using a standard JSON formatted POST request, you can set the `maxSupportedTransactionVersion` when retrieving a specific block: - -```bash -curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d \ -'{"jsonrpc": "2.0", "id":1, "method": "getBlock", "params": [430, { - "encoding":"json", - "maxSupportedTransactionVersion":0, - "transactionDetails":"full", - "rewards":false -}]}' -``` - -## How to create a Versioned Transaction - -Versioned transactions can be created similar to the older method of creating transactions. There are differences in using certain libraries that should be noted. - -Below is an example of how to create a Versioned Transaction, using the `@solana/web3.js` library, to send perform a SOL transfer between two accounts. - -#### Notes: - -- `payer` is a valid `Keypair` wallet, funded with SOL -- `toAccount` a valid `Keypair` - -Firstly, import the web3.js library and create a `connection` to your desired cluster. - -We then define the recent `blockhash` and `minRent` we will need for our transaction and the account: - -```js -const web3 = require("@solana/web3.js"); - -// connect to the cluster and get the minimum rent for rent exempt status -const connection = new web3.Connection(web3.clusterApiUrl("devnet")); -let minRent = await connection.getMinimumBalanceForRentExemption(0); -let blockhash = await connection - .getLatestBlockhash() - .then((res) => res.blockhash); -``` - -Create an `array` of all the `instructions` you desire to send in your transaction. In this example below, we are creating a simple SOL transfer instruction: - -```js -// create an array with your desired `instructions` -const instructions = [ - web3.SystemProgram.transfer({ - fromPubkey: payer.publicKey, - toPubkey: toAccount.publicKey, - lamports: minRent, - }), -]; -``` - -Next, construct a `MessageV0` formatted transaction message with your desired `instructions`: - -```js -// create v0 compatible message -const messageV0 = new web3.TransactionMessage({ - payerKey: payer.publicKey, - recentBlockhash: blockhash, - instructions, -}).compileToV0Message(); -``` - -Then, create a new `VersionedTransaction`, passing in our v0 compatible message: - -```js -const transaction = new web3.VersionedTransaction(messageV0); - -// sign your transaction with the required `Signers` -transaction.sign([payer]); -``` - -You can sign the transaction by either: - -- passing an array of `signatures` into the `VersionedTransaction` method, or -- call the `transaction.sign()` method, passing an array of the required `Signers` - -> NOTE: -> After calling the `transaction.sign()` method, all the previous transaction `signatures` will be fully replaced by new signatures created from the provided in `Signers`. - -After your `VersionedTransaction` has been signed by all required accounts, you can send it to the cluster and `await` the response: - -```js -// send our v0 transaction to the cluster -const txid = await connection.sendTransaction(transaction); -console.log(`https://explorer.solana.com/tx/${txid}?cluster=devnet`); -``` - -> NOTE: -> Unlike `legacy` transactions, sending a `VersionedTransaction` via `sendTransaction` does **NOT** support transaction signing via passing in an array of `Signers` as the second parameter. You will need to sign the transaction before calling `connection.sendTransaction()`. - -## More Resources - -- using [Versioned Transactions for Address Lookup Tables](./lookup-tables.md#how-to-create-an-address-lookup-table) -- view an [example of a v0 transaction](https://explorer.solana.com/tx/3jpoANiFeVGisWRY5UP648xRXs3iQasCHABPWRWnoEjeA93nc79WrnGgpgazjq4K9m8g2NJoyKoWBV1Kx5VmtwHQ/?cluster=devnet) on Solana Explorer -- read the [accepted proposal](./../proposals/versioned-transactions.md) for Versioned Transaction and Address Lookup Tables diff --git a/docs/src/economics_overview.md b/docs/src/economics_overview.md deleted file mode 100644 index 51997f07cc..0000000000 --- a/docs/src/economics_overview.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Solana Economics Overview ---- - -**Subject to change.** - -Solana’s crypto-economic system is designed to promote a healthy, long term self-sustaining economy with participant incentives aligned to the security and decentralization of the network. The main participants in this economy are validation-clients. Their contributions to the network, state validation, and their requisite incentive mechanisms are discussed below. - -The main channels of participant remittances are referred to as -protocol-based rewards and transaction fees. Protocol-based rewards -are generated from inflationary issuances from a protocol-defined inflation schedule. These rewards will constitute the total protocol-based reward delivered to validation clients, the remaining sourced from transaction fees. In the early days of the network, it is likely that protocol-based rewards, deployed based on predefined issuance schedule, will drive the majority of participant incentives to participate in the network. - -These protocol-based rewards are calculated per epoch and distributed across the active -delegated stake and validator set (per validator commission). As discussed further below, the per annum inflation rate is based on a pre-determined disinflationary schedule. This provides the network with supply predictability which supports long term economic stability and security. - -Transaction fees are participant-to-participant transfers, attached to network interactions as a motivation and compensation for the inclusion and execution of a proposed transaction. A mechanism for long-term economic stability and forking protection through partial burning of each transaction fee is also discussed below. - -First, an overview of the inflation design is presented. This section starts with defining and clarifying [Terminology](inflation/terminology.md) commonly used subsequently in the discussion of inflation and the related components. Following that, we outline Solana's proposed [Inflation Schedule](inflation/inflation_schedule.md), i.e. the specific parameters that uniquely parameterize the protocol-driven inflationary issuance over time. Next is a brief section on [Adjusted Staking Yield](inflation/adjusted_staking_yield.md), and how token dilution might influence staking behavior. - -An overview of [Transaction Fees](transaction_fees.md) on Solana is followed by a discussion of [Storage Rent Economics](storage_rent_economics.md) in which we describe an implementation of storage rent to account for the externality costs of maintaining the active state of the ledger. diff --git a/docs/src/validator/faq.md b/docs/src/faq.md similarity index 72% rename from docs/src/validator/faq.md rename to docs/src/faq.md index 4ae38152ae..35a17467f8 100644 --- a/docs/src/validator/faq.md +++ b/docs/src/faq.md @@ -5,23 +5,23 @@ sidebar_label: Frequently Asked Questions ### What is a validator? -A validator is a computer that runs a software program to verify transactions that are added to the Solana blockchain. A validator can be a voting validator or a non voting validator. To learn more, see [what is a validator](./overview/what-is-a-validator.md). +A validator is a computer that runs a software program to verify transactions that are added to the Solana blockchain. A validator can be a voting validator or a non voting validator. To learn more, see [what is a validator](./what-is-a-validator.md). ### What is an RPC node? -An RPC node is also a computer that runs the validator software. Typically, an RPC node does not vote on the network. Instead the RPC node's job is to respond to API requests. See [what is an rpc node](./overview/what-is-an-rpc-node.md) for more information. +An RPC node is also a computer that runs the validator software. Typically, an RPC node does not vote on the network. Instead the RPC node's job is to respond to API requests. See [what is an rpc node](./what-is-an-rpc-node.md) for more information. ### What is a cluster? -For a definition and an overview of the topic, see [what is a cluster?](../cluster/overview.md). Solana maintains several clusters. For details on each, see [Solana clusters](../clusters.md). +For a definition and an overview of the topic, see [what is a cluster?](./clusters/index.md). Solana maintains several clusters. For details on each, see [Solana clusters](./clusters/available.md). ### What is Proof of Stake? -Proof of Stake (PoS) is a blockchain architecture. Solana is a Proof of Stake blockchain. To read more, see [Proof of Stake](./overview/what-is-a-validator.md#proof-of-stake). +Proof of Stake (PoS) is a blockchain architecture. Solana is a Proof of Stake blockchain. To read more, see [Proof of Stake](./what-is-a-validator.md#proof-of-stake). ### What is Proof of Work? Is running a Solana validator the same as mining? -No, a Solana validator uses Proof of Stake. It does not use Proof of Work (often called mining). See [Proof of Work: For Contrast](./overview/what-is-a-validator.md#proof-of-stake). +No, a Solana validator uses Proof of Stake. It does not use Proof of Work (often called mining). See [Proof of Work: For Contrast](./what-is-a-validator.md#proof-of-stake). ### Who can operate a validator? @@ -33,18 +33,18 @@ No, all Solana clusters are permissionless. There is no limit to the number of ### What are the hardware requirements for running a validator? -See [validator requirements](../running-validator/validator-reqs.md). +See [validator requirements](./operations/requirements.md). ### Can I run my validator at home? Anyone can join the cluster including home users. You must make sure that your system can perform well and keep up with the cluster. Many home internet connections are not suitable to run a Solana validator. Most operators choose to operate their validator in a data center either by using a server provider or by supplying your own hardware at a colocation data center. -See the [validator requirements](../running-validator/validator-reqs.md) for more information. +See the [validator requirements](./operations/requirements.md) for more information. ### What skills does a Solana validator operator need? -See [Solana validator prerequisites](./overview/validator-prerequisites.md). +See [Solana validator prerequisites](./operations/prerequisites.md). ### What are the economics of running a validator? -See [economics of running a validator](./overview/running-validator-or-rpc-node.md#economics-of-running-a-consensus-validator). \ No newline at end of file +See [economics of running a validator](./operations/validator-or-rpc-node.md#economics-of-running-a-consensus-validator). \ No newline at end of file diff --git a/docs/src/getstarted/hello-world.md b/docs/src/getstarted/hello-world.md deleted file mode 100644 index beb8eacf5f..0000000000 --- a/docs/src/getstarted/hello-world.md +++ /dev/null @@ -1,242 +0,0 @@ ---- -title: "Hello World Quickstart Guide" -description: 'This "hello world" quickstart guide will demonstrate how to setup, build, and deploy your first Solana program in your browser with Solana Playground.' -keywords: - - playground - - solana pg - - on chain - - rust - - native program - - tutorial - - intro to solana development - - blockchain developer - - blockchain tutorial - - web3 developer ---- - -For this "hello world" quickstart guide, we will use [Solana Playground](https://beta.solpg.io), a browser based IDE to develop and deploy our Solana program. To use it, you do **NOT** have to install any software on your computer. Simply open Solana Playground in your browser of choice, and you are ready to write and deploy Solana programs. - -## What you will learn - -- How to get started with Solana Playground -- How to create a Solana wallet on Playground -- How to program a basic Solana program in Rust -- How to build and deploy a Solana Rust program -- How to interact with your on chain program using JavaScript - -## Using Solana Playground - -[Solana Playground](https://beta.solpg.io) is browser based application that will let you write, build, and deploy on chain Solana programs. All from your browser. No installation needed. - -It is a great developer resource for getting started with Solana development, especially on Windows. - -### Import our example project - -In a new tab in your browser, open our example "_Hello World_" project on Solana Playground: https://beta.solpg.io/6314a69688a7fca897ad7d1d - -Next, import the project into your local workspace by clicking the "**Import**" icon and naming your project `hello_world`. - -![Import the get started Solana program on Solana Playground](/img/quickstarts/solana-get-started-import-on-playground.png) - -> If you do **not** import the program into **your** Solana Playground, then you will **not** be able to make changes to the code. But you **will** still be able to build and deploy the code to a Solana cluster. - -### Create a Playground wallet - -Normally with [local development](./local.md), you will need to create a file system wallet for use with the Solana CLI. But with the Solana Playground, you only need to click a few buttons to create a browser based wallet. - -:::caution -Your _Playground Wallet_ will be saved in your browser's local storage. Clearing your browser cache will remove your saved wallet. When creating a new wallet, you will have the option to save a local copy of your wallet's keypair file. -::: - -Click on the red status indicator button at the bottom left of the screen, (optionally) save your wallet's keypair file to your computer for backup, then click "**Continue**". - -After your Playground Wallet is created, you will notice the bottom of the window now states your wallet's address, your SOL balance, and the Solana cluster you are connected to (Devnet is usually the default/recommended, but a "localhost" [test validator](./local.md) is also acceptable). - -## Create a Solana program - -The code for your Rust based Solana program will live in your `src/lib.rs` file. Inside `src/lib.rs` you will be able to import your Rust crates and define your logic. Open your `src/lib.rs` file within Solana Playground. - -### Import the `solana_program` crate - -At the top of `lib.rs`, we import the `solana-program` crate and bring our needed items into the local namespace: - -```rust -use solana_program::{ - account_info::AccountInfo, - entrypoint, - entrypoint::ProgramResult, - pubkey::Pubkey, - msg, -}; -``` - -### Write your program logic - -Every Solana program must define an `entrypoint` that tells the Solana runtime where to start executing your on chain code. Your program's [entrypoint](../developing/on-chain-programs/developing-rust#program-entrypoint) should provide a public function named `process_instruction`: - -```rust -// declare and export the program's entrypoint -entrypoint!(process_instruction); - -// program entrypoint's implementation -pub fn process_instruction( - program_id: &Pubkey, - accounts: &[AccountInfo], - instruction_data: &[u8] -) -> ProgramResult { - // log a message to the blockchain - msg!("Hello, world!"); - - // gracefully exit the program - Ok(()) -} -``` - -Every on chain program should return the `Ok` [result enum](https://doc.rust-lang.org/std/result/) with a value of `()`. This tells the Solana runtime that your program executed successfully without errors. - -Our program above will simply [log a message](../developing/on-chain-programs/debugging#logging) of "_Hello, world!_" to the blockchain cluster, then gracefully exit with `Ok(())`. - -### Build your program - -On the left sidebar, select the "**Build & Deploy**" tab. Next, click the "Build" button. - -If you look at the Playground's terminal, you should see your Solana program begin to compile. Once complete, you will see a success message. - -![Viewing a successful build of your Rust based program](/img/quickstarts/solana-get-started-successful-build.png) - -:::caution -You may receive _warning_ when your program is compiled due to unused variables. Don't worry, these warning will not affect your build. They are due to our very simple program not using all the variables we declared in the `process_instruction` function. -::: - -### Deploy your program - -You can click the "Deploy" button to deploy your first program to the Solana blockchain. Specifically to your selected cluster (e.g. Devnet, Testnet, etc). - -After each deployment, you will see your Playground Wallet balance change. By default, Solana Playground will automatically request SOL airdrops on your behalf to ensure your wallet has enough SOL to cover the cost of deployment. - -> Note: -> If you need more SOL, you can airdrop more by typing airdrop command in the playground terminal: - -```sh -solana airdrop 2 -``` - -![Build and deploy your Solana program to the blockchain](/img/quickstarts/solana-get-started-build-and-deploy.png) - -### Find your program id - -When executing a program using [web3.js](../developing/clients/javascript-reference.md) or from [another Solana program](../developing/programming-model/calling-between-programs.md), you will need to provide the `program id` (aka public address of your program). - -Inside Solana Playground's **Build & Deploy** sidebar, you can find your `program id` under the **Program Credentials** dropdown. - -#### Congratulations! - -You have successfully setup, built, and deployed a Solana program using the Rust language directly in your browser. Next, we will demonstrate how to interact with your on chain program. - -## Interact with your on chain program - -Once you have successfully deployed a Solana program to the blockchain, you will want to be able to interact with that program. - -Like most developers creating dApps and websites, we will interact with our on chain program using JavaScript. Specifically, will use the open source [NPM package](https://www.npmjs.com/package/@solana/web3.js) `@solana/web3.js` to aid in our client application. - -:::info -This web3.js package is an abstraction layer on top of the [JSON RPC API](/api) that reduced the need for rewriting common boilerplate, helping to simplify your client side application code. -::: - -### Initialize client - -We will be using Solana Playground for the client generation. Create a client folder by running `run` command in the playground terminal: - -```bash -run -``` - -We have created `client` folder and a default `client.ts`. This is where we will work for the rest of our `hello world` program. - -### Playground globals - -In playground, there are many utilities that are globally available for us to use without installing or setting up anything. Most important ones for our `hello world` program are `web3` for `@solana/web3.js` and `pg` for Solana Playground utilities. - -:::info -You can go over all of the available globals by pressing `CTRL+SPACE` (or `CMD+SPACE` on macOS) inside the editor. -::: - -### Call the program - -To execute your on chain program, you must send a [transaction](../developing/programming-model/transactions.md) to it. Each transaction submitted to the Solana blockchain contains a listing of instructions (and the program's that instruction will interact with). - -Here we create a new transaction and add a single `instruction` to it: - -```js -// create an empty transaction -const transaction = new web3.Transaction(); - -// add a hello world program instruction to the transaction -transaction.add( - new web3.TransactionInstruction({ - keys: [], - programId: new web3.PublicKey(pg.PROGRAM_ID), - }), -); -``` - -Each `instruction` must include all the keys involved in the operation and the program ID we want to execute. In this example `keys` is empty because our program only logs `hello world` and doesn't need any accounts. - -With our transaction created, we can submit it to the cluster: - -```js -// send the transaction to the Solana cluster -console.log("Sending transaction..."); -const txHash = await web3.sendAndConfirmTransaction( - pg.connection, - transaction, - [pg.wallet.keypair], -); -console.log("Transaction sent with hash:", txHash); -``` - -:::info -The first signer in the signers array is the transaction fee payer by default. We are signing with our keypair `pg.wallet.keypair`. -::: - -### Run the application - -With the client application written, you can run the code via the same `run` command. - -Once your application completes, you will see output similar to this: - -```sh -Running client... - client.ts: - My address: GkxZRRNPfaUfL9XdYVfKF3rWjMcj5md6b6mpRoWpURwP - My balance: 5.7254472 SOL - Sending transaction... - Transaction sent with hash: 2Ra7D9JoqeNsax9HmNq6MB4qWtKPGcLwoqQ27mPYsPFh3h8wignvKB2mWZVvdzCyTnp7CEZhfg2cEpbavib9mCcq -``` - -### Get transaction logs - -We will be using `solana-cli` directly in playground to get the information about any transaction: - -```sh -solana confirm -v -``` - -Change `` with the hash you received from calling `hello world` program. - -You should see `Hello, world!` in the **Log Messages** section of the output. 🎉 - -#### Congratulations!!! - -You have now written a client application for your on chain program. You are now a Solana developer! - -PS: Try to update your program's message then re-build, re-deploy, and re-execute your program. - -## Next steps - -See the links below to learn more about writing Solana programs: - -- [Setup your local development environment](./local.md) -- [Overview of writing Solana programs](../developing/on-chain-programs/overview) -- [Learn more about developing Solana programs with Rust](../developing/on-chain-programs/developing-Rust) -- [Debugging on chain programs](../developing/on-chain-programs/debugging) diff --git a/docs/src/getstarted/local.md b/docs/src/getstarted/local.md deleted file mode 100644 index 3a4358cac2..0000000000 --- a/docs/src/getstarted/local.md +++ /dev/null @@ -1,166 +0,0 @@ ---- -title: "Local Development Quickstart" -description: "This quickstart guide will demonstrate how to quickly install and setup your local Solana development environment." -keywords: - - rust - - cargo - - toml - - program - - tutorial - - intro to solana development - - blockchain developer - - blockchain tutorial - - web3 developer ---- - -This quickstart guide will demonstrate how to quickly install and setup your local development environment, getting you ready to start developing and deploying Solana programs to the blockchain. - -## What you will learn - -- How to install the Solana CLI locally -- How to setup a localhost Solana cluster/validator -- How to create a Solana wallet for developing -- How to airdrop SOL tokens for your wallet - -## Install the Solana CLI - -To interact with the Solana network from your terminal, you will need to install the [Solana CLI tool suite](./../cli/install-solana-cli-tools) on your local system. - -
    -macOS / Linux / Windows Subsystem for Linux (WSL) -Open your favourite terminal application and install the CLI by running: - -```bash -sh -c "$(curl -sSfL https://release.solana.com/stable/install)" -``` - -Depending on your system, the end of the installer messaging may prompt you to - -```bash -Please update your PATH environment variable to include the solana programs: -``` - -If you get the above message, copy and paste the recommended command below it to update `PATH` - -Confirm you have the desired version of `solana` installed by running: - -```bash -solana --version -``` - -After a successful install, `solana-install update` may be used to easily update the Solana software to a newer version at any time. - -
    - -
    -Windows - -:::caution -[WSL](https://learn.microsoft.com/en-us/windows/wsl/install) is the recommended environment for Windows users. -::: - -- Open a Command Prompt (`cmd.exe`) as an Administrator - - - Search for Command Prompt in the Windows search bar. When the Command - Prompt app appears, right-click and select “Open as Administrator”. - If you are prompted by a pop-up window asking “Do you want to allow this app to - make changes to your device?”, click Yes. - -- Copy and paste the following command, then press Enter to download the Solana - installer into a temporary directory: - -```bash -cmd /c "curl https://release.solana.com/stable/solana-install-init-x86_64-pc-windows-msvc.exe --output C:\solana-install-tmp\solana-install-init.exe --create-dirs" -``` - -- Copy and paste the following command, then press Enter to install the latest - version of Solana. If you see a security pop-up by your system, please select - to allow the program to run. - -```bash -C:\solana-install-tmp\solana-install-init.exe stable -``` - -- When the installer is finished, press Enter. - -- Close the command prompt window and re-open a new command prompt window as a - normal user -- Confirm you have the desired version of `solana` installed by entering: - -```bash -solana --version -``` - -After a successful install, `solana-install update` may be used to easily update the Solana software to a newer version at any time. -
    - - -## Setup a localhost blockchain cluster - -The Solana CLI comes with the [test validator](./../developing/test-validator.md) built in. This command line tool will allow you to run a full blockchain cluster on your machine. - -```bash -solana-test-validator -``` - -> **PRO TIP:** -> Run the Solana test validator in a new/separate terminal window that will remain open. The command line program must remain running for your localhost cluster to remain online and ready for action. - -Configure your Solana CLI to use your localhost validator for all your future terminal commands: - -```bash -solana config set --url localhost -``` - -At any time, you can view your current Solana CLI configuration settings: - -```bash -solana config get -``` - -## Create a file system wallet - -To deploy a program with Solana CLI, you will need a Solana wallet with SOL tokens to pay for the cost of transactions. - -Let's create a simple file system wallet for testing: - -```bash -solana-keygen new -``` - -By default, the `solana-keygen` command will create a new file system wallet located at `~/.config/solana/id.json`. You can manually specify the output file location using the `--outfile /path` option. - -> **NOTE:** -> If you already have a file system wallet saved at the default location, this command will **NOT** override it (unless you explicitly force override using the `--force` flag). - -### Set your new wallet as default - -With your new file system wallet created, you must tell the Solana CLI to use this wallet to deploy and take ownership of your on chain program: - -```bash -solana config set -k ~/.config/solana/id.json -``` - -## Airdrop SOL tokens to your wallet - -Once your new wallet is set as the default, you can request a free airdrop of SOL tokens to it: - -```bash -solana airdrop 2 -``` - -> **NOTE:** -> The `solana airdrop` command has a limit of how many SOL tokens can be requested _per airdrop_ for each cluster (localhost, testnet, or devent). If your airdrop transaction fails, lower your airdrop request quantity and try again. - -You can check your current wallet's SOL balance any time: - -```bash -solana balance -``` - -## Next steps - -See the links below to learn more about writing Rust based Solana programs: - -- [Create and deploy a Solana Rust program](./rust.md) -- [Overview of writing Solana programs](../developing/on-chain-programs/overview) diff --git a/docs/src/getstarted/overview.md b/docs/src/getstarted/overview.md deleted file mode 100644 index ddc0aa94fa..0000000000 --- a/docs/src/getstarted/overview.md +++ /dev/null @@ -1,240 +0,0 @@ ---- -title: "Introduction to Solana Development" -description: - "Learn about the basic development concepts of the Solana blockchain." -keywords: - - accounts - - transactions - - nft - - solana basics - - tutorial - - intro to solana development - - blockchain developer - - blockchain tutorial - - web3 developer ---- - -Welcome to the Solana developer docs! - -This guide contains step-by-step instructions on how to get started. Before we -get into the hands on part of the guide, we'll cover basic concepts that all -developers need to be familiar with to build on Solana: - -- Transactions -- Accounts -- Programs - -## What you will learn - -- What the developer workflows look like -- What transactions, accounts, and programs are -- Test networks and other tools - -## An overview of Solana developer workflows - -The Solana network can be thought of as one massive global computer where anyone -can store and execute code for a fee. Deployed code is called a program, often -referred to as a "smart contract" on other blockchains. To interact with a -program, you need to send a transaction on the blockchain from a client. - -Here's a high level representation of this. It’s important to note that this is -an oversimplification of the Solana network for the purposes of learning in an -easy-to-understand way. - -![Solana developer workflows program-client model](/img/quickstarts/solana-overview-client-program.png) - -### Program development - -The first development workflow allows you to to create and deploy custom Rust, C -and C++ programs directly to the blockchain. Once these programs are deployed, -anyone who knows how to communicate with them can use them. - -You can communicate with these programs by writing dApps with any of the -available client SDKs (or the [CLI](../cli.md)), all of which use the -[JSON RPC API](../api) under the hood. - -### Client development - -The second development workflow is the dApp side where you can write dApps that -communicate with deployed programs. Your apps can submit transactions with -instructions to these programs via a client SDK to create a wide variety of -applications such as wallets, exchanges and more. The most popular apps are -browser extension wallets and web apps, but you can build mobile/desktop apps or -anything that can communicate with the JSON RPC API. - -These two pieces work together to create a network of dApps and programs that -can communicate with each other to update the state and query the blockchain. - -## Wallets - -A wallet is a pair of public and private keys that are used to verify actions on -the blockchain. The public key is used to identify the account and the private -key is used to sign transactions. - -## Transactions - -A transaction is the fundamental unit of activity on the Solana blockchain: it's -a signed data structure that contains instructions for the network to perform a -particular operation like transferring tokens. - -You need a transaction to create, update or delete data on-chain. You can read -data without a transaction. - -All transactions interact with programs on the network - these can be system -programs or user built programs. Transactions tell the program what they want to -do with a bunch of instructions, and if they're valid, the program will execute -them and update the state of the blockchain. Think of it like a write command -that can be rejected if certain conditions aren't met. - -Here's a visual representation of what a transaction contains: -![Visual layout of a transaction](/img/transaction.svg) - -- Signatures: An array of digital signatures from the transaction's signers. -- Message: The actual instructions that the transaction is issuing to the - network. - - Message header: 3 `uint8s` describing how many accounts will sign the - payload, how many won’t, and how many are read-only. - - Account addresses: an array of addresses of the accounts that will be used - in the transaction. - - Recent blockhash: a unique value that identifies a recent block - this - ensures the transaction is not too old and is not re-processed. - - Instructions: which program to call, which accounts to use, and any - additional data needed for the program to execute the instruction. - -Transactions can be created and signed using clients via SDKs, or even on-chain -programs. - -You can learn more about transactions -[here](../developing/programming-model/transactions.md). - -### Instructions - -Instructions are the most basic operational unit on Solana. A transaction can -contain one or more instructions. Instructions are executed sequentially in the -order they are provided in the transaction by programs on the blockchain. If any -part of an instruction fails, the entire transaction will fail. - -Here's what an instruction looks like: - -| Item | Description | -| ------------ | -------------------------------------------------------------------------------------------------------- | -| `Program ID` | The ID of the program being called | -| `Accounts` | The accounts that the instruction wants to read or modify | -| `Data` | Input data provided to the program as additional information or parameters in the format of a byte array | - -You can read more about instructions -[here](../developing/programming-model/transactions#instructions). - -### Transaction Fees - -Every time you submit a transaction, somebody on the network is providing space -and processing power to make it happen. To facilitate this, transactions on -Solana require a fee to be paid in Lamports, which are the smallest units of SOL -(like cents to a dollar or paise to a rupee). One SOL is equal to 1,000,000,000 -Lamports, and one Lamport has a value of 0.000000001 SOL. This fee is paid to -the validators who process the transaction. - -Transactions fees are calculated based on two main parts: - -- a statically set base fee per signature, and -- the computational resources used during the transaction, measured in - "[_compute units_](../terminology.md#compute-units)" - -The more work a transaction requires, the more compute units it will use, and -the more it will cost. - -You can read more about transaction fees [here](../transaction_fees.md). - -## Accounts - -Accounts on Solana are storage spaces that can hold arbitrary data up to 10MB. -They're used to store data, user programs, and native system programs. - -If a program needs to store state between transactions, it does so using -accounts. This means that all programs on Solana are stateless - they don't -store any state data, only code. If an account stores program code, it's marked -"executable" and can process instructions. - -The easiest way to think of an account is like a file. Users can have many -different files. Developers can write programs that can "talk" to these files. -In the same way that a Linux user uses a path to look up a file, a Solana client -uses an address to look up an account. The address is a 256-bit public key. Also -like a file, an account includes metadata that tells the runtime who is allowed -to access the data and how. This prevents unauthorized changes to the data in -the account. - -Unlike a file, the account includes metadata for the lifetime of the file. -Solana accounts have a unique lifecycle. When an account is created, it needs to -be assigned some space, and tokens are required to rent this space. If an -account doesn't have enough tokens to cover the rent, it will be removed. -However, if the account does hold enough tokens to cover the rent for two years, -it's considered "rent-exempt" and won't be deleted. - -You can read more about accounts -[here](../developing/programming-model/accounts.md). - -## Programs - -Programs are the foundation of the Solana blockchain. They're responsible for -everything that happens on the network: creating accounts, processing -transactions, collecting fees, and more. - -Programs process instructions from both end users and other programs. All -programs are stateless: any data they interact with is stored in separate -accounts that are passed in via instructions. - -There are two sets of programs that are maintained by the Solana Labs team: -[Native Programs](../developing/runtime-facilities/programs.md) and the -[Solana Program Library (SPL)](https://spl.solana.com/). These serve as core -building blocks for on-chain interactions. Native programs are used for core -blockchain functionality like creating new accounts, assigning ownership, -transferring SOL, and more. SPL programs are used for creating, swapping, and -lending tokens, as well as generating stake pools and maintaining an on-chain -name service. - -You can interact with both native programs and SPL programs easily using the -Solana CLI and the SDKs, allowing you to create complete dApps without writing -Rust. You can also build on top of any user programs that have been deployed to -the network - all you need is the program's address and how it works: the -account structures, instructions, and error codes. - -Developers most commonly write programs in Rust using frameworks such as Anchor. -However, programs can be written in any language that compiles to BPF, including -C++ and Move. - -You can learn more about programs [here](../developing/intro/programs.md). - -## Testing and developing environments - -When developing on Solana you have a few options for environments. - -The easiest and quickest way to get started is the -[Solana Playground](https://beta.solpg.io) - a browser based IDE that allows you -to write, deploy, and test programs. - -The most popular setup is [local development](local.md) with a local validator -that you run on your machine - this allows you to test your programs locally -before deploying them to any network. - -In each environment, you'll be using one of three networks: - -- Mainnet Beta - the "production" network where all the action happens. - Transactions cost real money here. -- Testnet - used for stress testing recent releases. Focused on network - performance, stability, and validator behavior. -- Devnet - the primary network for development. Most closely resembles Mainnet - Beta, but tokens are not real. - -Devnet has a faucet that allows you to get free SOL to test with. It costs $0 to -do development on Solana. - -Check out the [clusters page](../clusters.md) for more information on these. - -## Next steps - -You're now ready to get started building on Solana! - -- [Deploy your first Solana program in the browser](./hello-world.md) -- [Setup your local development environment](./local.md) -- [Get started building programs locally with Rust](./rust.md) -- [Overview of writing Solana programs](../developing/on-chain-programs/overview) diff --git a/docs/src/getstarted/rust.md b/docs/src/getstarted/rust.md deleted file mode 100644 index 661806928c..0000000000 --- a/docs/src/getstarted/rust.md +++ /dev/null @@ -1,157 +0,0 @@ ---- -title: "Rust Program Quickstart" -description: "This quickstart guide will demonstrate how to quickly setup, build, and deploy your first Rust based Solana program to the blockchain." -keywords: - - rust - - cargo - - toml - - program - - tutorial - - intro to solana development - - blockchain developer - - blockchain tutorial - - web3 developer ---- - -Rust is the most common programming language to write Solana programs with. This quickstart guide will demonstrate how to quickly setup, build, and deploy your first Rust based Solana program to the blockchain. - -> **NOTE: ** -> This guide uses the Solana CLI and assumes you have setup your local development environment. Checkout our [local development quickstart guide](./local.md) here to quickly get setup. - -## What you will learn - -- How to install the Rust language locally -- How to initialize a new Solana Rust program -- How to code a basic Solana program in Rust -- How to build and deploy your Rust program - -## Install Rust and Cargo - -To be able to compile Rust based Solana programs, install the Rust language and Cargo (the Rust package manager) using [Rustup](https://rustup.rs/): - -```bash -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -``` - -## Run your localhost validator - -The Solana CLI comes with the [test validator](../developing/test-validator.md) built in. This command line tool will allow you to run a full blockchain cluster on your machine. - -```bash -solana-test-validator -``` - -> **PRO TIP:** -> Run the Solana test validator in a new/separate terminal window that will remain open. This command line program must remain running for your localhost validator to remain online and ready for action. - -Configure your Solana CLI to use your localhost validator for all your future terminal commands and Solana program deployment: - -```bash -solana config set --url localhost -``` - -## Create a new Rust library with Cargo - -Solana programs written in Rust are _libraries_ which are compiled to [BPF bytecode](../developing/on-chain-programs/faq.md#berkeley-packet-filter-bpf) and saved in the `.so` format. - -Initialize a new Rust library named `hello_world` via the Cargo command line: - -```bash -cargo init hello_world --lib -cd hello_world -``` - -Add the `solana-program` crate to your new Rust library: - -```bash -cargo add solana-program -``` - -Open your `Cargo.toml` file and add these required Rust library configuration settings, updating your project name as appropriate: - -```toml -[lib] -name = "hello_world" -crate-type = ["cdylib", "lib"] -``` - -## Create your first Solana program - -The code for your Rust based Solana program will live in your `src/lib.rs` file. Inside `src/lib.rs` you will be able to import your Rust crates and define your logic. Open your `src/lib.rs` file in your favorite editor. - -At the top of `lib.rs`, import the `solana-program` crate and bring our needed items into the local namespace: - -```rust -use solana_program::{ - account_info::AccountInfo, - entrypoint, - entrypoint::ProgramResult, - pubkey::Pubkey, - msg, -}; -``` - -Every Solana program must define an `entrypoint` that tells the Solana runtime where to start executing your on chain code. Your program's [entrypoint](../developing/on-chain-programs/developing-rust#program-entrypoint) should provide a public function named `process_instruction`: - -```rust -// declare and export the program's entrypoint -entrypoint!(process_instruction); - -// program entrypoint's implementation -pub fn process_instruction( - program_id: &Pubkey, - accounts: &[AccountInfo], - instruction_data: &[u8] -) -> ProgramResult { - // log a message to the blockchain - msg!("Hello, world!"); - - // gracefully exit the program - Ok(()) -} -``` - -Every on chain program should return the `Ok` [result enum](https://doc.rust-lang.org/std/result/) with a value of `()`. This tells the Solana runtime that your program executed successfully without errors. - -This program above will simply [log a message](../developing/on-chain-programs/debugging#logging) of "_Hello, world!_" to the blockchain cluster, then gracefully exit with `Ok(())`. - -## Build your Rust program - -Inside a terminal window, you can build your Solana Rust program by running in the root of your project (i.e. the directory with your `Cargo.toml` file): - -```bash -cargo build-bpf -``` - -> **NOTE:** -> After each time you build your Solana program, the above command will output the build path of your compiled program's `.so` file and the default keyfile that will be used for the program's address. -> `cargo build-bpf` installs the toolchain from the currently installed solana CLI tools. You may need to upgrade those tools if you encounter any version incompatibilities. - -## Deploy your Solana program - -Using the Solana CLI, you can deploy your program to your currently selected cluster: - -```bash -solana program deploy ./target/deploy/hello_world.so -``` - -Once your Solana program has been deployed (and the transaction [finalized](../cluster/commitments.md)), the above command will output your program's public address (aka its "program id"). - -```bash -# example output -Program Id: EFH95fWg49vkFNbAdw9vy75tM7sWZ2hQbTTUmuACGip3 -``` - -#### Congratulations! - -You have successfully setup, built, and deployed a Solana program using the Rust language. - -> PS: Check your Solana wallet's balance again after you deployed. See how much SOL it cost to deploy your simple program? - -## Next steps - -See the links below to learn more about writing Rust based Solana programs: - -- [Overview of writing Solana programs](../developing/on-chain-programs/overview) -- [Learn more about developing Solana programs with Rust](../developing/on-chain-programs/developing-Rust) -- [Debugging on chain programs](../developing/on-chain-programs/debugging) diff --git a/docs/src/history.md b/docs/src/history.md deleted file mode 100644 index a3fd7a7c11..0000000000 --- a/docs/src/history.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: History ---- - -In November of 2017, Anatoly Yakovenko published a whitepaper describing Proof -of History, a technique for keeping time between computers that do not trust -one another. From Anatoly's previous experience designing distributed systems -at Qualcomm, Mesosphere and Dropbox, he knew that a reliable clock makes -network synchronization very simple. When synchronization is simple the -resulting network can be blazing fast, bound only by network bandwidth. - -Anatoly watched as blockchain systems without clocks, such as Bitcoin and -Ethereum, struggled to scale beyond 15 transactions per second worldwide when -centralized payment systems such as Visa required peaks of 65,000 tps. Without -a clock, it was clear they'd never graduate to being the global payment system -or global supercomputer most had dreamed them to be. When Anatoly solved the -problem of getting computers that don’t trust each other to agree on time, he -knew he had the key to bring 40 years of distributed systems research to the -world of blockchain. The resulting cluster wouldn't be just 10 times faster, or -a 100 times, or a 1,000 times, but 10,000 times faster, right out of the gate! - -Anatoly's implementation began in a private codebase and was implemented in the -C programming language. Greg Fitzgerald, who had previously worked with Anatoly -at semiconductor giant Qualcomm Incorporated, encouraged him to reimplement the -project in the Rust programming language. Greg had worked on the LLVM compiler -infrastructure, which underlies both the Clang C/C++ compiler as well as the -Rust compiler. Greg claimed that the language's safety guarantees would improve -software productivity and that its lack of a garbage collector would allow -programs to perform as well as those written in C. Anatoly gave it a shot and -just two weeks later, had migrated his entire codebase to Rust. Sold. With -plans to weave all the world's transactions together on a single, scalable -blockchain, Anatoly called the project Loom. - -On February 13th of 2018, Greg began prototyping the first open source -implementation of Anatoly's whitepaper. The project was published to GitHub -under the name Silk in the loomprotocol organization. On February 28th, Greg -made his first release, demonstrating 10 thousand signed transactions could be -verified and processed in just over half a second. Shortly after, another -former Qualcomm cohort, Stephen Akridge, demonstrated throughput could be -massively improved by offloading signature verification to graphics processors. -Anatoly recruited Greg, Stephen and three others to co-found a company, then -called Loom. - -Around the same time, Ethereum-based project Loom Network sprung up and many -people were confused about whether they were the same project. The Loom team -decided it would rebrand. They chose the name Solana, a nod to a small beach -town North of San Diego called Solana Beach, where Anatoly, Greg and Stephen -lived and surfed for three years when they worked for Qualcomm. On March 28th, -the team created the Solana GitHub organization and renamed Greg's prototype -Silk to Solana. - -In June of 2018, the team scaled up the technology to run on cloud-based -networks and on July 19th, published a 50-node, permissioned, public testnet -consistently supporting bursts of 250,000 transactions per second. In a later -release in December, called v0.10 Pillbox, the team published a permissioned -testnet running 150 nodes on a gigabit network and demonstrated soak tests -processing an _average_ of 200 thousand transactions per second with bursts -over 500 thousand. The project was also extended to support on-chain programs -written in the C programming language and run concurrently in a safe execution -environment called SBF. diff --git a/docs/src/implemented-proposals/commitment.md b/docs/src/implemented-proposals/commitment.md index 3297dd9fe7..43b6f8a7fd 100644 --- a/docs/src/implemented-proposals/commitment.md +++ b/docs/src/implemented-proposals/commitment.md @@ -4,7 +4,7 @@ title: Commitment The commitment metric aims to give clients a measure of the network confirmation and stake levels on a particular block. Clients can then use this information to -derive their own [measures of commitment](../cluster/commitments.md). +derive their own [measures of commitment](../consensus/commitments.md). # Calculation RPC diff --git a/docs/src/implemented-proposals/durable-tx-nonces.md b/docs/src/implemented-proposals/durable-tx-nonces.md index 72aa701f39..d2de019db5 100644 --- a/docs/src/implemented-proposals/durable-tx-nonces.md +++ b/docs/src/implemented-proposals/durable-tx-nonces.md @@ -71,8 +71,8 @@ stored hash, and thus unusable. To initialize a newly created account, an `InitializeNonceAccount` instruction must be issued. This instruction takes one parameter, the `Pubkey` of the account's -[authority](../offline-signing/durable-nonce.md#nonce-authority). Nonce accounts -must be [rent-exempt](rent.md#two-tiered-rent-regime) to meet the data-persistence +[authority](../cli/examples/durable-nonce.md#nonce-authority). Nonce accounts +must be [rent-exempt](./rent.md#two-tiered-rent-regime) to meet the data-persistence requirements of the feature, and as such, require that sufficient lamports be deposited before they can be initialized. Upon successful initialization, the cluster's most recent blockhash is stored along with specified nonce authority @@ -83,7 +83,7 @@ value. It stores the cluster's most recent blockhash in the account's state data failing if that matches the value already stored there. This check prevents replaying transactions within the same block. -Due to nonce accounts' [rent-exempt](rent.md#two-tiered-rent-regime) requirement, +Due to nonce accounts' [rent-exempt](./rent.md#two-tiered-rent-regime) requirement, a custom withdraw instruction is used to move funds out of the account. The `WithdrawNonceAccount` instruction takes a single argument, lamports to withdraw, and enforces rent-exemption by preventing the account's balance from falling @@ -92,12 +92,12 @@ would be zero lamports, which makes the account eligible for deletion. This account closure detail has an additional requirement that the stored nonce value must not match the cluster's most recent blockhash, as per `AdvanceNonceAccount`. -The account's [nonce authority](../offline-signing/durable-nonce.md#nonce-authority) +The account's [nonce authority](../cli/examples/durable-nonce.md#nonce-authority) can be changed using the `AuthorizeNonceAccount` instruction. It takes one parameter, the `Pubkey` of the new authority. Executing this instruction grants full control over the account and its balance to the new authority. -> `AdvanceNonceAccount`, `WithdrawNonceAccount` and `AuthorizeNonceAccount` all require the current [nonce authority](../offline-signing/durable-nonce.md#nonce-authority) for the account to sign the transaction. +> `AdvanceNonceAccount`, `WithdrawNonceAccount` and `AuthorizeNonceAccount` all require the current [nonce authority](../cli/examples/durable-nonce.md#nonce-authority) for the account to sign the transaction. ### Runtime Support diff --git a/docs/src/implemented-proposals/implemented-proposals.md b/docs/src/implemented-proposals/index.md similarity index 100% rename from docs/src/implemented-proposals/implemented-proposals.md rename to docs/src/implemented-proposals/index.md diff --git a/docs/src/implemented-proposals/leader-validator-transition.md b/docs/src/implemented-proposals/leader-validator-transition.md index 3793cb890b..e3281252f1 100644 --- a/docs/src/implemented-proposals/leader-validator-transition.md +++ b/docs/src/implemented-proposals/leader-validator-transition.md @@ -2,15 +2,23 @@ title: Leader-to-Validator Transition --- -A validator typically spends its time validating blocks. If, however, a staker delegates its stake to a validator, it will occasionally be selected as a _slot leader_. As a slot leader, the validator is responsible for producing blocks during an assigned _slot_. A slot has a duration of some number of preconfigured _ticks_. The duration of those ticks are estimated with a _PoH Recorder_ described later in this document. +A validator typically spends its time validating blocks. If, however, a staker +delegates its stake to a validator, it will occasionally be selected as a _slot +leader_. As a slot leader, the validator is responsible for producing blocks +during an assigned _slot_. A slot has a duration of some number of preconfigured +_ticks_. The duration of those ticks are estimated with a _PoH Recorder_ +described later in this document. ## BankFork -BankFork tracks changes to the bank state over a specific slot. Once the final tick has been registered the state is frozen. Any attempts to write to are rejected. +BankFork tracks changes to the bank state over a specific slot. Once the final +tick has been registered the state is frozen. Any attempts to write to are +rejected. ## Validator -A validator operates on many different concurrent forks of the bank state until it generates a PoH hash with a height within its leader slot. +A validator operates on many different concurrent forks of the bank state until +it generates a PoH hash with a height within its leader slot. ## Slot Leader @@ -18,35 +26,58 @@ A slot leader builds blocks on top of only one fork, the one it last voted on. ## PoH Recorder -Slot leaders and validators use a PoH Recorder for both estimating slot height and for recording transactions. +Slot leaders and validators use a PoH Recorder for both estimating slot height +and for recording transactions. ### PoH Recorder when Validating -The PoH Recorder acts as a simple VDF when validating. It tells the validator when it needs to switch to the slot leader role. Every time the validator votes on a fork, it should use the fork's latest [blockhash](../terminology.md#blockhash) to re-seed the VDF. Re-seeding solves two problems. First, it synchronizes its VDF to the leader's, allowing it to more accurately determine when its leader slot begins. Second, if the previous leader goes down, all wallclock time is accounted for in the next leader's PoH stream. For example, if one block is missing when the leader starts, the block it produces should have a PoH duration of two blocks. The longer duration ensures the following leader isn't attempting to snip all the transactions from the previous leader's slot. +The PoH Recorder acts as a simple VDF when validating. It tells the validator +when it needs to switch to the slot leader role. Every time the validator votes +on a fork, it should use the fork's latest +[blockhash](https://solana.com/docs/terminology#blockhash) to re-seed the VDF. +Re-seeding solves two problems. First, it synchronizes its VDF to the leader's, +allowing it to more accurately determine when its leader slot begins. Second, if +the previous leader goes down, all wallclock time is accounted for in the next +leader's PoH stream. For example, if one block is missing when the leader +starts, the block it produces should have a PoH duration of two blocks. The +longer duration ensures the following leader isn't attempting to snip all the +transactions from the previous leader's slot. ### PoH Recorder when Leading -A slot leader use the PoH Recorder to record transactions, locking their positions in time. The PoH hash must be derived from a previous leader's last block. If it isn't, its block will fail PoH verification and be rejected by the cluster. +A slot leader use the PoH Recorder to record transactions, locking their +positions in time. The PoH hash must be derived from a previous leader's last +block. If it isn't, its block will fail PoH verification and be rejected by the +cluster. -The PoH Recorder also serves to inform the slot leader when its slot is over. The leader needs to take care not to modify its bank if recording the transaction would generate a PoH height outside its designated slot. The leader, therefore, should not commit account changes until after it generates the entry's PoH hash. When the PoH height falls outside its slot any transactions in its pipeline may be dropped or forwarded to the next leader. Forwarding is preferred, as it would minimize network congestion, allowing the cluster to advertise higher TPS capacity. +The PoH Recorder also serves to inform the slot leader when its slot is over. +The leader needs to take care not to modify its bank if recording the +transaction would generate a PoH height outside its designated slot. The leader, +therefore, should not commit account changes until after it generates the +entry's PoH hash. When the PoH height falls outside its slot any transactions in +its pipeline may be dropped or forwarded to the next leader. Forwarding is +preferred, as it would minimize network congestion, allowing the cluster to +advertise higher TPS capacity. ## Validator Loop -The PoH Recorder manages the transition between modes. Once a ledger is replayed, the validator can run until the recorder indicates it should be the slot leader. As a slot leader, the node can then execute and record transactions. +The PoH Recorder manages the transition between modes. Once a ledger is +replayed, the validator can run until the recorder indicates it should be the +slot leader. As a slot leader, the node can then execute and record +transactions. -The loop is synchronized to PoH and does a synchronous start and stop of the slot leader functionality. After stopping, the validator's TVU should find itself in the same state as if a different leader had sent it the same block. The following is pseudocode for the loop: +The loop is synchronized to PoH and does a synchronous start and stop of the +slot leader functionality. After stopping, the validator's TVU should find +itself in the same state as if a different leader had sent it the same block. +The following is pseudocode for the loop: 1. Query the LeaderScheduler for the next assigned slot. -2. Run the TVU over all the forks. 1. TVU will send votes to what it believes is the "best" fork. 2. After each vote, restart the PoH Recorder to run until the next assigned - - slot. - +2. Run the TVU over all the forks. 1. TVU will send votes to what it believes is + the "best" fork. 2. After each vote, restart the PoH Recorder to run until + the next assigned slot. 3. When time to be a slot leader, start the TPU. Point it to the last fork the - TVU voted on. - -4. Produce entries until the end of the slot. 1. For the duration of the slot, the TVU must not vote on other forks. 2. After the slot ends, the TPU freezes its BankFork. After freezing, - - the TVU may resume voting. - +4. Produce entries until the end of the slot. 1. For the duration of the slot, + the TVU must not vote on other forks. 2. After the slot ends, the TPU freezes + its BankFork. After freezing, the TVU may resume voting. 5. Goto 1. diff --git a/docs/src/implemented-proposals/rpc-transaction-history.md b/docs/src/implemented-proposals/rpc-transaction-history.md index c8eb878eae..5e7e783d48 100644 --- a/docs/src/implemented-proposals/rpc-transaction-history.md +++ b/docs/src/implemented-proposals/rpc-transaction-history.md @@ -10,13 +10,14 @@ fall back to the external data store. The affected RPC endpoints are: -- [getFirstAvailableBlock](../api/http#getfirstavailableblock) -- [getConfirmedBlock](../api/http#getconfirmedblock) -- [getConfirmedBlocks](../api/http#getconfirmedblocks) -- [getConfirmedSignaturesForAddress](../api/http#getconfirmedsignaturesforaddress) -- [getConfirmedTransaction](../api/http#getconfirmedtransaction) -- [getSignatureStatuses](../api/http#getsignaturestatuses) -- [getBlockTime](../api/http#getblocktime) + +- [getFirstAvailableBlock](https://solana.com/docs/rpc/http/getfirstavailableblock) +- [getConfirmedBlock](https://solana.com/docs/rpc/http/getconfirmedblock) +- [getConfirmedBlocks](https://solana.com/docs/rpc/http/getconfirmedblocks) +- [getConfirmedSignaturesForAddress](https://solana.com/docs/rpc/http/getconfirmedsignaturesforaddress) +- [getConfirmedTransaction](https://solana.com/docs/rpc/http/getconfirmedtransaction) +- [getSignatureStatuses](https://solana.com/docs/rpc/http/getsignaturestatuses) +- [getBlockTime](https://solana.com/docs/rpc/http/getblocktime) Some system design constraints: diff --git a/docs/src/implemented-proposals/tower-bft.md b/docs/src/implemented-proposals/tower-bft.md index cdc936af39..ef34d11eae 100644 --- a/docs/src/implemented-proposals/tower-bft.md +++ b/docs/src/implemented-proposals/tower-bft.md @@ -14,14 +14,14 @@ For brevity this design assumes that a single voter with a stake is deployed as ## Time -The Solana cluster generates a source of time via a Verifiable Delay Function we are calling [Proof of History](../cluster/synchronization.md). +The Solana cluster generates a source of time via a Verifiable Delay Function we are calling [Proof of History](../consensus/synchronization.md). The unit of time is called a "slot". Each slot has a designated leader that can produce a block `B`. The `slot` of block `B` is designated `slot(B)`. A leader does not necessarily need to generate a block for its slot, in which case there may not be blocks for some slots. -For more details, see [fork generation](../cluster/fork-generation.md) and [leader rotation](../cluster/leader-rotation.md). +For more details, see [fork generation](../consensus/fork-generation.md) and [leader rotation](../consensus/leader-rotation.md). ## Votes diff --git a/docs/src/implemented-proposals/transaction-fees.md b/docs/src/implemented-proposals/transaction-fees.md index 042db21a50..1163c3fcae 100644 --- a/docs/src/implemented-proposals/transaction-fees.md +++ b/docs/src/implemented-proposals/transaction-fees.md @@ -6,7 +6,7 @@ title: Deterministic Transaction Fees Before sending a transaction to the cluster, a client may query the network to determine what the transaction's fee will be via the rpc request -[getFeeForMessage](../api/http#getfeeformessage). +[getFeeForMessage](https://solana.com/docs/rpc/http/getfeeformessage). ## Fee Parameters diff --git a/docs/src/index.mdx b/docs/src/index.mdx index 2d24609c44..422404b0a7 100644 --- a/docs/src/index.mdx +++ b/docs/src/index.mdx @@ -9,56 +9,49 @@ description: "Solana is a high performance network that is utilized for a range # displayed_sidebar: introductionSidebar --- -# Solana Documentation +# Solana Validator Documentation Solana is a blockchain built for mass adoption. It's a high performance network that is utilized for a range of use cases, including finance, NFTs, payments, and gaming. Solana operates as a single global state machine, and is open, interoperable and decentralized. -## Getting started +## Command Line Interface and Tool Suite -Dive right into Solana to start building or setup your tooling. +To get started using the Solana Command Line (CLI) tools: -- [Setup local environment](/cli) - Install the Solana CLI to get your local - development environment setup -- [Hello World in your browser](getstarted/hello-world) - Build and deploy your - first on-chain Solana program, directly in your browser using Solana - Playground +- [Install the Solana CLI Tool Suite](./cli/install.md) - Quickly get setup + locally with the CLI, optionally build from source +- [Introduction to the CLI conventions](./cli/intro.md) - Understand the common + conventions used within the CLI tool suite +- [Choose a cluster](./cli/examples/choose-a-cluster.md) - Select a Solana + network cluster to connect (e.g. `devnet`, `testnet`, `mainnet-beta`) +- [Create a wallet](./cli/wallets/index.md) - Create a command line wallet for + use within the CLI and beyond -## Start learning - -Build a strong understanding of the core concepts that make Solana different -from other blockchains. - -- [Transactions](./developing/programming-model/transactions) - Collection of - instructions for the blockchain to execute -- [Accounts](./developing/programming-model/accounts) - Data and state storage - mechanism for Solana -- [Programs](./developing/intro/programs) - The executable code used to perform - actions on the blockchain -- [Cross-Program Invocation](./developing/programming-model/calling-between-programs) - - Core of the "composability" of Solana, this is how programs can "call" each - other. - -## Understanding the architecture +## Understanding the Architecture Get to know the underlying architecture of how the proof-of-stake blockchain -works. +works: -- [Validators](./validator/anatomy) - the individual nodes that are the backbone - of the network -- [Clusters](./cluster/overview) - a collection of validators that work together - for consensus +- [Clusters](./clusters/index.md) - a collection of validators that work + together for consensus +- [Validators](./validator/anatomy.md) - the individual nodes that are the + backbone of the network +- [Runtime](./runtime/programs.md) - the native programs that are core to the + validator and the blockchain -## Running a validator +## Running a Validator Explore what it takes to operate a Solana validator and help secure the network. -- [System requirements](./running-validator/validator-reqs) - Recommended - hardware requirements and expected SOL needed to operate a validator -- [Quick start guide](./validator/get-started/setup-a-validator) - Setup a - validator and get connected to a cluster for the first time +- [Validator vs RPC node](./operations/validator-or-rpc-node.md) - Understand + the important differences between voting and non-voting validators on the + network +- [System requirements](./operations/requirements.md) - Recommended hardware + requirements and expected SOL needed to operate a validator +- [Quick start guide](./operations/setup-a-validator.md) - Setup a validator and + get connected to a cluster for the first time ## Learn more diff --git a/docs/src/inflation/adjusted_staking_yield.md b/docs/src/inflation/adjusted_staking_yield.md deleted file mode 100644 index ba1974b4f1..0000000000 --- a/docs/src/inflation/adjusted_staking_yield.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -title: Adjusted Staking Yield ---- - -### Token Dilution - -Similarly we can look at the expected _Staked Dilution_ (i.e. _Adjusted Staking Yield_) and _Un-staked Dilution_ as previously defined. Again, _dilution_ in this context is defined as the change in fractional representation (i.e. ownership) of a set of tokens within a larger set. In this sense, dilution can be a positive value: an increase in fractional ownership (staked dilution / _Adjusted Staking Yield_), or a negative value: a decrease in fractional ownership (un-staked dilution). - -We are interested in the relative change in ownership of staked vs un-staked tokens as the overall token pool increases with inflation issuance. As discussed, this issuance is distributed only to staked token holders, increasing the staked token fractional representation of the _Total Current Supply_. - -Continuing with the same _Inflation Schedule_ parameters as above, we see the fraction of staked supply grow as shown below. - -![](/img/p_ex_staked_supply_w_range_initial_stake.png) - -Due to this relative change in representation, the proportion of stake of any token holder will also change as a function of the _Inflation Schedule_ and the proportion of all tokens that are staked. - -Of initial interest, however, is the _dilution of **un-staked** tokens_, or $D_{us}$. In the case of un-staked tokens, token dilution is only a function of the _Inflation Schedule_ because the amount of un-staked tokens doesn't change over time. - -This can be seen by explicitly calculating un-staked dilution as $D_{us}$. The un-staked proportion of the token pool at time $t$ is $P_{us}(t_{N})$ and $I_{t}$ is the incremental inflation rate applied between any two consecutive time points. $SOL_{us}(t)$ and $SOL_{total}(t)$ is the amount of un-staked and total SOL on the network, respectively, at time $t$. Therefore $P_{us}(t) = SOL_{us}(t)/SOL_{total}(t)$. - -$$ -\begin{aligned} - D_{us} &= \left( \frac{P_{us}(t_{1}) - P_{us}(t_{0})}{P_{us}(t_{0})} \right)\\ - &= \left( \frac{ \left( \frac{SOL_{us}(t_{2})}{SOL_{total}(t_{2})} \right) - \left( \frac{SOL_{us}(t_{1})}{SOL_{total}(t_{1})} \right)}{ \left( \frac{SOL_{us}(t_{1})}{SOL_{total}(t_{1})} \right) } \right)\\ - -\end{aligned} -$$ - -However, because inflation issuance only increases the total amount and the un-staked supply doesn't change: - -$$ -\begin{aligned} - SOL_{us}(t_2) &= SOL_{us}(t_1)\\ - SOL_{total}(t_2) &= SOL_{total}(t_1)\times (1 + I_{t_1})\\ -\end{aligned} -$$ - -So $D_{us}$ becomes: - -$$ -\begin{aligned} - D_{us} &= \left( \frac{ \left( \frac{SOL_{us}(t_{1})}{SOL_{total}(t_{1})\times (1 + I_{1})} \right) - \left( \frac{SOL_{us}(t_{1})}{SOL_{total}(t_{1})} \right)}{ \left( \frac{SOL_{us}(t_{1})}{SOL_{total}(t_{1})} \right) } \right)\\ - D_{us} &= \frac{1}{(1 + I_{1})} - 1\\ -\end{aligned} -$$ - -Or generally, dilution for un-staked tokens over any time frame undergoing inflation $I$: - -$$ -D_{us} = -\frac{I}{I + 1} \\ -$$ - -So as guessed, this dilution is independent of the total proportion of staked tokens and only depends on inflation rate. This can be seen with our example _Inflation Schedule_ here: - -![p_ex_unstaked_dilution](/img/p_ex_unstaked_dilution.png) - -### Estimated Adjusted Staked Yield - -We can do a similar calculation to determine the _dilution_ of staked token holders, or as we've defined here as the **_Adjusted Staked Yield_**, keeping in mind that dilution in this context is an _increase_ in proportional ownership over time. We'll use the terminology _Adjusted Staked Yield_ to avoid confusion going forward. - -To see the functional form, we calculate, $Y_{adj}$, or the _Adjusted Staked Yield_ (to be compared to _D\_{us}_ the dilution of un-staked tokens above), where $P_{s}(t)$ is the staked proportion of token pool at time $t$ and $I_{t}$ is the incremental inflation rate applied between any two consecutive time points. The definition of $Y_{adj}$ is therefore: - -$$ - Y_{adj} = \frac{P_s(t_2) - P_s(t_1)}{P_s(t_1)}\\ -$$ - -As seen in the plot above, the proportion of staked tokens increases with inflation issuance. Letting $SOL_s(t)$ and $SOL_{\text{total}}(t)$ represent the amount of staked and total SOL at time $t$ respectively: - -$$ - P_s(t_2) = \frac{SOL_s(t_1) + SOL_{\text{total}}(t_1)\times I(t_1)}{SOL_{\text{total}}(t_1)\times (1 + I(t_1))}\\ -$$ - -Where $SOL_{\text{total}}(t_1)\times I(t_1)$ is the additional inflation issuance added to the staked token pool. Now we can write $Y_{adj}$ in common terms $t_1 = t$: - -$$ -\begin{aligned} -Y_{adj} &= \frac{\frac{SOL_s(t) + SOL_{\text{total}}(t)\times I(t)}{SOL_{\text{total}}(t)\times (1 + I(t))} - \frac{SOL_s(t)}{SOL_{\text{total}}(t)} }{ \frac{SOL_s(t)}{SOL_{\text{total}}(t)} } \\ - &= \frac{ SOL_{\text{total}}(t)\times (SOL_s(t) + SOL_{\text{total}}(t)\times I(t)) }{ SOL_s(t)\times SOL_{\text{total}}\times (1 + I(t)) } -1 \\ -\end{aligned} -$$ - -which simplifies to: - -$$ -Y_{adj} = \frac{ 1 + I(t)/P_s(t) }{ 1 + I(t) } - 1\\ -$$ - -So we see that the _Adjusted Staked Yield_ a function of the inflation rate and the percent of staked tokens on the network. We can see this plotted for various staking fractions here: - -![p_ex_adjusted_staked_yields](/img/p_ex_adjusted_staked_yields.png) - -It is also clear that in all cases, dilution of un-staked tokens $>$ adjusted staked yield (i.e. dilution of staked tokens). Explicitly we can look at the _relative dilution of un-staked tokens to staked tokens:_ $D_{us}/Y_{adj}$. Here the relationship to inflation drops out and the relative dilution, i.e. the impact of staking tokens vs not staking tokens, is purely a function of the % of the total token supply staked. From above - -$$ -\begin{aligned} -Y_{adj} &= \frac{ 1 + I/P_s }{ 1 + I } - 1,~\text{and}\\ -D_{us} &= -\frac{I}{I + 1},~\text{so} \\ -\frac{D_{us}}{Y_{adj}} &= \frac{ \frac{I}{I + 1} }{ \frac{ 1 + I/P_s }{ 1 + I } - 1 } \\ -\end{aligned} -$$ - -which simplifies as, - -$$ - \begin{aligned} - \frac{D_{us}}{Y_{adj}} &= \frac{ I }{ 1 + \frac{I}{P_s} - (1 + I)}\\ - &= \frac{ I }{ \frac{I}{P_s} - I}\\ - \frac{D_{us}}{Y_{adj}}&= \frac{ P_s }{ 1 - P_s}\\ - \end{aligned} -$$ - -Where we can see a primary dependence of the relative dilution of un-staked tokens to staked tokens is on the function of the proportion of total tokens staked. As shown above, the proportion of total tokens staked changes over time (i.e. $P_s = P_s(t)$ due to the re-staking of inflation issuance thus we see relative dilution grow over time as: - -![p_ex_relative_dilution](/img/p_ex_relative_dilution.png) - -As might be intuitive, as the total fraction of staked tokens increases the relative dilution of un-staked tokens grows dramatically. E.g. with $80\%$ of the network tokens staked, an un-staked token holder will experience ~$400\%$ more dilution than a staked holder. - -Again, this represents the change in fractional change in ownership of staked tokens and illustrates the built-in incentive for token holder to stake their tokens to earn _Staked Yield_ and avoid _Un-staked Dilution_. diff --git a/docs/src/inflation/inflation_schedule.md b/docs/src/inflation/inflation_schedule.md deleted file mode 100644 index 0b83a75f4e..0000000000 --- a/docs/src/inflation/inflation_schedule.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Solana's Proposed Inflation Schedule ---- - -As mentioned above, the network's _Inflation Schedule_ is uniquely described by three parameters: _Initial Inflation Rate_, _Disinflation Rate_ and _Long-term Inflation Rate_. When considering these numbers, there are many factors to take into account: - -- A large portion of the SOL issued via inflation will be distributed to stake-holders in proportion to the SOL they have staked. We want to ensure that the _Inflation Schedule_ design results in reasonable _Staking Yields_ for token holders who delegate SOL and for validation service providers (via commissions taken from _Staking Yields_). -- The primary driver of _Staked Yield_ is the amount of SOL staked divided by the total amount of SOL (% of total SOL staked). Therefore the distribution and delegation of tokens across validators are important factors to understand when determining initial inflation parameters. -- Yield throttling is a current area of research that would impact _staking-yields_. This is not taken into consideration in the discussion here or the modeling below. -- Overall token issuance - i.e. what do we expect the Current Total Supply to be in 10 years, or 20 years? -- Long-term, steady-state inflation is an important consideration not only for sustainable support for the validator ecosystem and the Solana Foundation grant programs, but also should be tuned in consideration with expected token losses and burning over time. -- The rate at which we expect network usage to grow, as a consideration to the disinflationary rate. Over time, we plan for inflation to drop and expect that usage will grow. - -Based on these considerations and the community discussions following the initial design, the Solana Foundation proposes the following Inflation Schedule parameters: - -- Initial Inflation Rate: $8\%$ -- Disinflation Rate: $-15\%$ -- Long-term Inflation Rate: $1.5\%$ - -These parameters define the proposed _Inflation Schedule_. Below we show implications of these parameters. These plots only show the impact of inflation issuances given the Inflation Schedule as parameterized above. They _do not account_ for other factors that may impact the Total Supply such as fee/rent burning, slashing or other unforeseen future token destruction events. Therefore, what is presented here is an **upper limit** on the amount of SOL issued via inflation. - -![](/img/p_inflation_schedule.png) - -In the above graph we see the annual inflation rate [$\%$] over time, given the inflation parameters proposed above. - -![](/img/p_total_supply.png) - -Similarly, here we see the _Total Current Supply_ of SOL [MM] over time, assuming an initial _Total Current Supply_ of `488,587,349 SOL` (i.e. for this example, taking the _Total Current Supply_ as of `2020-01-25` and simulating inflation starting from that day). - -Setting aside validator uptime and commissions, the expected Staking Yield and Adjusted Staking Yield metrics are then primarily a function of the % of total SOL staked on the network. Therefore we can we can model _Staking Yield_, if we introduce an additional parameter _% of Staked SOL_: - -$$ -\%~\text{SOL Staked} = \frac{\text{Total SOL Staked}}{\text{Total Current Supply}} -$$ - -This parameter must be estimated because it is a dynamic property of the token holders and staking incentives. The values of _% of Staked SOL_ presented here range from $60\% - 90\%$, which we feel covers the likely range we expect to observe, based on feedback from the investor and validator communities as well as what is observed on comparable Proof-of-Stake protocols. - -![](/img/p_ex_staked_yields.png) - -Again, the above shows an example _Staked Yield_ that a staker might expect over time on the Solana network with the _Inflation Schedule_ as specified. This is an idealized _Staked Yield_ as it neglects validator uptime impact on rewards, validator commissions, potential yield throttling and potential slashing incidents. It additionally ignores that _% of Staked SOL_ is dynamic by design - the economic incentives set up by this _Inflation Schedule_ are more clearly seen when _Token Dilution_ is taken into account (see the **Adjusted Staking Yield** section below). diff --git a/docs/src/inflation/terminology.md b/docs/src/inflation/terminology.md deleted file mode 100644 index e9de2b8656..0000000000 --- a/docs/src/inflation/terminology.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: Terminology ---- - -Many terms are thrown around when discussing inflation and the related components (e.g. rewards/yield/interest), we try to define and clarify some commonly used concept here: - -### Total Current Supply [SOL] - -The total amount of tokens (locked or unlocked) that have been generated (via genesis block or protocol inflation) minus any tokens that have been burnt (via transaction fees or other mechanism) or slashed. At network launch, 500,000,000 SOL were instantiated in the genesis block. Since then the Total Current Supply has been reduced by the burning of transaction fees and a planned token reduction event. Solana’s _Total Current Supply_ can be found at https://explorer.solana.com/supply - -### Inflation Rate [%] - -The Solana protocol will automatically create new tokens on a predetermined inflation schedule (discussed below). The _Inflation Rate [%]_ is the annualized growth rate of the _Total Current Supply_ at any point in time. - -### Inflation Schedule - -A deterministic description of token issuance over time. The Solana Foundation is proposing a disinflationary _Inflation Schedule_. I.e. Inflation starts at its highest value, the rate reduces over time until stabilizing at a predetermined long-term inflation rate (see discussion below). This schedule is completely and uniquely parameterized by three numbers: - -- **Initial Inflation Rate [%]**: The starting _Inflation Rate_ for when inflation is first enabled. Token issuance rate can only decrease from this point. -- **Disinflation Rate [%]**: The rate at which the _Inflation Rate_ is reduced. -- **Long-term Inflation Rate [%]**: The stable, long-term _Inflation Rate_ to be expected. - -### Effective Inflation Rate [%] - -The inflation rate actually observed on the Solana network after accounting for other factors that might decrease the _Total Current Supply_. Note that it is not possible for tokens to be created outside of what is described by the _Inflation Schedule_. - -- While the _Inflation Schedule_ determines how the protocol issues SOL, this neglects the concurrent elimination of tokens in the ecosystem due to various factors. The primary token burning mechanism is the burning of a portion of each transaction fee. $50\%$ of each transaction fee is burned, with the remaining fee retained by the validator that processes the transaction. -- Additional factors such as loss of private keys and slashing events should also be considered in a holistic analysis of the _Effective Inflation Rate_. For example, it’s estimated that $10-20\%$ of all BTC have been lost and are unrecoverable and that networks may experience similar yearly losses at the rate of $1-2\%$. - -### Staking Yield [%] - -The rate of return (aka _interest_) earned on SOL staked on the network. It is often quoted as an annualized rate (e.g. "the network _staking yield_ is currently $10\%$ per year"). - -- _Staking yield_ is of great interest to validators and token holders who wish to delegate their tokens to avoid token dilution due to inflation (the extent of which is discussed below). -- $100\%$ of inflationary issuances are to be distributed to staked token-holders in proportion to their staked SOL and to validators who charge a commission on the rewards earned by their delegated SOL. - - There may be future consideration for an additional split of inflation issuance with the introduction of _Archivers_ into the economy. _Archivers_ are network participants who provide a decentralized storage service and should also be incentivized with token distribution from inflation issuances for this service. - Similarly, early designs specified a fixed percentage of inflationary issuance to be delivered to the Foundation treasury for operational expenses and future grants. However, inflation will be launching without any portion allocated to the Foundation. -- _Staking yield_ can be calculated from the _Inflation Schedule_ along with the fraction of the _Total Current Supply_ that is staked at any given time. The explicit relationship is given by: - -$$ -\begin{aligned} -\text{Staking Yield} =~&\text{Inflation Rate}\times\text{Validator Uptime}~\times \\ -&\left( 1 - \text{Validator Fee} \right) \times \left( \frac{1}{\%~\text{SOL Staked}} \right) \\ -\text{where:}\\ -\%~\text{SOL Staked} &= \frac{\text{Total SOL Staked}}{\text{Total Current Supply}} -\end{aligned} -$$ - -### Token Dilution [%] - -Dilution is defined here as the change in proportional representation of a set of tokens within a larger set due to the introduction of new tokens. In practical terms, we discuss the dilution of staked or un-staked tokens due to the introduction and distribution of inflation issuance across the network. As will be shown below, while dilution impacts every token holder, the _relative_ dilution between staked and un-staked tokens should be the primary concern to un-staked token holders. Staking tokens, which will receive their proportional distribution of inflation issuance, should assuage any dilution concerns for staked token holders. I.e. dilution from 'inflation' is offset by the distribution of new tokens to staked token holders, nullifying the 'dilutive' effects of the inflation for that group. - -### Adjusted Staking Yield [%] - -A complete appraisal of earning potential from staking tokens should take into account staked _Token Dilution_ and its impact on the _Staking Yield_. For this, we define the _Adjusted Staking Yield_ as the change in fractional token supply ownership of staked tokens due to the distribution of inflation issuance. I.e. the positive dilutive effects of inflation. diff --git a/docs/src/integrations/exchange.md b/docs/src/integrations/exchange.md deleted file mode 100644 index 2e8d70f9cc..0000000000 --- a/docs/src/integrations/exchange.md +++ /dev/null @@ -1,924 +0,0 @@ ---- -title: Add Solana to Your Exchange ---- - -This guide describes how to add Solana's native token SOL to your cryptocurrency -exchange. - -## Node Setup - -We highly recommend setting up at least two nodes on high-grade computers/cloud -instances, upgrading to newer versions promptly, and keeping an eye on service -operations with a bundled monitoring tool. - -This setup enables you: - -- to have a self-administered gateway to the Solana mainnet-beta cluster to get - data and submit withdrawal transactions -- to have full control over how much historical block data is retained -- to maintain your service availability even if one node fails - -Solana nodes demand relatively high computing power to handle our fast blocks -and high TPS. For specific requirements, please see -[hardware recommendations](../running-validator/validator-reqs.md). - -To run an api node: - -1. [Install the Solana command-line tool suite](../cli/install-solana-cli-tools.md) -2. Start the validator with at least the following parameters: - -```bash -solana-validator \ - --ledger \ - --identity \ - --entrypoint \ - --expected-genesis-hash \ - --rpc-port 8899 \ - --no-voting \ - --enable-rpc-transaction-history \ - --limit-ledger-size \ - --known-validator \ - --only-known-rpc -``` - -Customize `--ledger` to your desired ledger storage location, and `--rpc-port` to the port you want to expose. - -The `--entrypoint` and `--expected-genesis-hash` parameters are all specific to the cluster you are joining. -[Current parameters for Mainnet Beta](../clusters.md#example-solana-validator-command-line-2) - -The `--limit-ledger-size` parameter allows you to specify how many ledger -[shreds](../terminology.md#shred) your node retains on disk. If you do not -include this parameter, the validator will keep the entire ledger until it runs -out of disk space. The default value attempts to keep the ledger disk usage -under 500GB. More or less disk usage may be requested by adding an argument to -`--limit-ledger-size` if desired. Check `solana-validator --help` for the -default limit value used by `--limit-ledger-size`. More information about -selecting a custom limit value is [available -here](https://github.com/solana-labs/solana/blob/583cec922b6107e0f85c7e14cb5e642bc7dfb340/core/src/ledger_cleanup_service.rs#L15-L26). - -Specifying one or more `--known-validator` parameters can protect you from booting from a malicious snapshot. [More on the value of booting with known validators](../running-validator/validator-start.md#known-validators) - -Optional parameters to consider: - -- `--private-rpc` prevents your RPC port from being published for use by other nodes -- `--rpc-bind-address` allows you to specify a different IP address to bind the RPC port - -### Automatic Restarts and Monitoring - -We recommend configuring each of your nodes to restart automatically on exit, to -ensure you miss as little data as possible. Running the solana software as a -systemd service is one great option. - -For monitoring, we provide -[`solana-watchtower`](https://github.com/solana-labs/solana/blob/master/watchtower/README.md), -which can monitor your validator and detect with the `solana-validator` process -is unhealthy. It can directly be configured to alert you via Slack, Telegram, -Discord, or Twillio. For details, run `solana-watchtower --help`. - -```bash -solana-watchtower --validator-identity -``` - -> You can find more information about the [best practices for Solana Watchtower](../validator/best-practices/monitoring.md#solana-watchtower) here in the docs. - -#### New Software Release Announcements - -We release new software frequently (around 1 release / week). -Sometimes newer versions include incompatible protocol changes, which -necessitate timely software update to avoid errors in processing blocks. - -Our official release announcements for all kinds of releases (normal and -security) are communicated via a [discord](https://solana.com/discord) channel called -`#mb-announcement` -(`mb` stands for `mainnet-beta`). - -Like staked validators, we expect any exchange-operated validators to be updated -at your earliest convenience within a business day or two after a normal release -announcement. For security-related releases, more urgent action may be needed. - -### Ledger Continuity - -By default, each of your nodes will boot from a snapshot provided by one of your -known validators. This snapshot reflects the current state of the chain, but -does not contain the complete historical ledger. If one of your node exits and -boots from a new snapshot, there may be a gap in the ledger on that node. In -order to prevent this issue, add the `--no-snapshot-fetch` parameter to your -`solana-validator` command to receive historical ledger data instead of a -snapshot. - -Do not pass the `--no-snapshot-fetch` parameter on your initial boot as it's not -possible to boot the node all the way from the genesis block. Instead boot from -a snapshot first and then add the `--no-snapshot-fetch` parameter for reboots. - -It is important to note that the amount of historical ledger available to your -nodes from the rest of the network is limited at any point in time. Once -operational if your validators experience significant downtime they may not be -able to catch up to the network and will need to download a new snapshot from a -known validator. In doing so your validators will now have a gap in its -historical ledger data that cannot be filled. - -### Minimizing Validator Port Exposure - -The validator requires that various UDP and TCP ports be open for inbound -traffic from all other Solana validators. While this is the most efficient mode of -operation, and is strongly recommended, it is possible to restrict the -validator to only require inbound traffic from one other Solana validator. - -First add the `--restricted-repair-only-mode` argument. This will cause the -validator to operate in a restricted mode where it will not receive pushes from -the rest of the validators, and instead will need to continually poll other -validators for blocks. The validator will only transmit UDP packets to other -validators using the _Gossip_ and _ServeR_ ("serve repair") ports, and only -receive UDP packets on its _Gossip_ and _Repair_ ports. - -The _Gossip_ port is bi-directional and allows your validator to remain in -contact with the rest of the cluster. Your validator transmits on the _ServeR_ -to make repair requests to obtaining new blocks from the rest of the network, -since Turbine is now disabled. Your validator will then receive repair -responses on the _Repair_ port from other validators. - -To further restrict the validator to only requesting blocks from one or more -validators, first determine the identity pubkey for that validator and add the -`--gossip-pull-validator PUBKEY --repair-validator PUBKEY` arguments for each -PUBKEY. This will cause your validator to be a resource drain on each validator -that you add, so please do this sparingly and only after consulting with the -target validator. - -Your validator should now only be communicating with the explicitly listed -validators and only on the _Gossip_, _Repair_ and _ServeR_ ports. - -## Setting up Deposit Accounts - -Solana accounts do not require any on-chain initialization; once they contain -some SOL, they exist. To set up a deposit account for your exchange, simply -generate a Solana keypair using any of our [wallet tools](../wallet-guide/cli.md). - -We recommend using a unique deposit account for each of your users. - -Solana accounts must be made rent-exempt by containing 2-years worth of -[rent](developing/programming-model/accounts.md#rent) in SOL. In order to find -the minimum rent-exempt balance for your deposit accounts, query the -[`getMinimumBalanceForRentExemption` endpoint](../api/http#getminimumbalanceforrentexemption): - -```bash -curl localhost:8899 -X POST -H "Content-Type: application/json" -d '{ - "jsonrpc": "2.0", - "id": 1, - "method": "getMinimumBalanceForRentExemption", - "params":[0] -}' - -# Result -{"jsonrpc":"2.0","result":890880,"id":1} -``` - -### Offline Accounts - -You may wish to keep the keys for one or more collection accounts offline for -greater security. If so, you will need to move SOL to hot accounts using our -[offline methods](../offline-signing.md). - -## Listening for Deposits - -When a user wants to deposit SOL into your exchange, instruct them to send a -transfer to the appropriate deposit address. - -### Versioned Transaction Migration - -When the Mainnet Beta network starts processing versioned transactions, exchanges -**MUST** make changes. If no changes are made, deposit detection will no longer -work properly because fetching a versioned transaction or a block containing -versioned transactions will return an error. - -- `{"maxSupportedTransactionVersion": 0}` - - The `maxSupportedTransactionVersion` parameter must be added to `getBlock` and - `getTransaction` requests to avoid disruption to deposit detection. The latest - transaction version is `0` and should be specified as the max supported - transaction version value. - -It's important to understand that versioned transactions allow users to create -transactions that use another set of account keys loaded from on-chain address -lookup tables. - -- `{"encoding": "jsonParsed"}` - - When fetching blocks and transactions, it's now recommended to use the - `"jsonParsed"` encoding because it includes all transaction account keys - (including those from lookup tables) in the message `"accountKeys"` list. - This makes it straightforward to resolve balance changes detailed in - `preBalances` / `postBalances` and `preTokenBalances` / `postTokenBalances`. - - If the `"json"` encoding is used instead, entries in `preBalances` / - `postBalances` and `preTokenBalances` / `postTokenBalances` may refer to - account keys that are **NOT** in the `"accountKeys"` list and need to be - resolved using `"loadedAddresses"` entries in the transaction metadata. - -### Poll for Blocks - -To track all the deposit accounts for your exchange, poll for each confirmed -block and inspect for addresses of interest, using the JSON-RPC service of your -Solana API node. - -- To identify which blocks are available, send a [`getBlocks`](../api/http#getblocks) request, - passing the last block you have already processed as the start-slot parameter: - -```bash -curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ - "jsonrpc": "2.0", - "id": 1, - "method": "getBlocks", - "params": [160017005, 160017015] -}' - -# Result -{"jsonrpc":"2.0","result":[160017005,160017006,160017007,160017012,160017013,160017014,160017015],"id":1} -``` - -Not every slot produces a block, so there may be gaps in the sequence of integers. - -- For each block, request its contents with a [`getBlock`](../api/http#getblock) request: - -### Block Fetching Tips - -- `{"rewards": false}` - -By default, fetched blocks will return information about validator fees on each -block and staking rewards on epoch boundaries. If you don't need this -information, disable it with the "rewards" parameter. - -- `{"transactionDetails": "accounts"}` - -By default, fetched blocks will return a lot of transaction info and metadata -that isn't necessary for tracking account balances. Set the "transactionDetails" -parameter to speed up block fetching. - -```bash -curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' -d '{ - "jsonrpc": "2.0", - "id": 1, - "method": "getBlock", - "params": [ - 166974442, - { - "encoding": "jsonParsed", - "maxSupportedTransactionVersion": 0, - "transactionDetails": "accounts", - "rewards": false - } - ] -}' - -# Result -{ - "jsonrpc": "2.0", - "result": { - "blockHeight": 157201607, - "blockTime": 1665070281, - "blockhash": "HKhao674uvFc4wMK1Cm3UyuuGbKExdgPFjXQ5xtvsG3o", - "parentSlot": 166974441, - "previousBlockhash": "98CNLU4rsYa2HDUyp7PubU4DhwYJJhSX9v6pvE7SWsAo", - "transactions": [ - ... (omit) - { - "meta": { - "err": null, - "fee": 5000, - "postBalances": [ - 1110663066, - 1, - 1040000000 - ], - "postTokenBalances": [], - "preBalances": [ - 1120668066, - 1, - 1030000000 - ], - "preTokenBalances": [], - "status": { - "Ok": null - } - }, - "transaction": { - "accountKeys": [ - { - "pubkey": "9aE476sH92Vz7DMPyq5WLPkrKWivxeuTKEFKd2sZZcde", - "signer": true, - "source": "transaction", - "writable": true - }, - { - "pubkey": "11111111111111111111111111111111", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o", - "signer": false, - "source": "lookupTable", - "writable": true - } - ], - "signatures": [ - "2CxNRsyRT7y88GBwvAB3hRg8wijMSZh3VNYXAdUesGSyvbRJbRR2q9G1KSEpQENmXHmmMLHiXumw4dp8CvzQMjrM" - ] - }, - "version": 0 - }, - ... (omit) - ] - }, - "id": 1 -} -``` - -The `preBalances` and `postBalances` fields allow you to track the balance -changes in every account without having to parse the entire transaction. They -list the starting and ending balances of each account in -[lamports](../terminology.md#lamport), indexed to the `accountKeys` list. For -example, if the deposit address of interest is -`G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o`, this transaction represents a -transfer of 1040000000 - 1030000000 = 10,000,000 lamports = 0.01 SOL - -If you need more information about the transaction type or other specifics, you -can request the block from RPC in binary format, and parse it using either our -[Rust SDK](https://github.com/solana-labs/solana) or -[Javascript SDK](https://github.com/solana-labs/solana-web3.js). - -### Address History - -You can also query the transaction history of a specific address. This is -generally _not_ a viable method for tracking all your deposit addresses over all -slots, but may be useful for examining a few accounts for a specific period of -time. - -- Send a [`getSignaturesForAddress`](../api/http#getsignaturesforaddress) - request to the api node: - -```bash -curl localhost:8899 -X POST -H "Content-Type: application/json" -d '{ - "jsonrpc": "2.0", - "id": 1, - "method": "getSignaturesForAddress", - "params": [ - "3M2b3tLji7rvscqrLAHMukYxDK2nB96Q9hwfV6QkdzBN", - { - "limit": 3 - } - ] -}' - -# Result -{ - "jsonrpc": "2.0", - "result": [ - { - "blockTime": 1662064640, - "confirmationStatus": "finalized", - "err": null, - "memo": null, - "signature": "3EDRvnD5TbbMS2mCusop6oyHLD8CgnjncaYQd5RXpgnjYUXRCYwiNPmXb6ZG5KdTK4zAaygEhfdLoP7TDzwKBVQp", - "slot": 148697216 - }, - { - "blockTime": 1662064434, - "confirmationStatus": "finalized", - "err": null, - "memo": null, - "signature": "4rPQ5wthgSP1kLdLqcRgQnkYkPAZqjv5vm59LijrQDSKuL2HLmZHoHjdSLDXXWFwWdaKXUuryRBGwEvSxn3TQckY", - "slot": 148696843 - }, - { - "blockTime": 1662064341, - "confirmationStatus": "finalized", - "err": null, - "memo": null, - "signature": "36Q383JMiqiobuPV9qBqy41xjMsVnQBm9rdZSdpbrLTGhSQDTGZJnocM4TQTVfUGfV2vEX9ZB3sex6wUBUWzjEvs", - "slot": 148696677 - } - ], - "id": 1 -} -``` - -- For each signature returned, get the transaction details by sending a - [`getTransaction`](../api/http#gettransaction) request: - -```bash -curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' -d '{ - "jsonrpc":"2.0", - "id":1, - "method":"getTransaction", - "params":[ - "2CxNRsyRT7y88GBwvAB3hRg8wijMSZh3VNYXAdUesGSyvbRJbRR2q9G1KSEpQENmXHmmMLHiXumw4dp8CvzQMjrM", - { - "encoding":"jsonParsed", - "maxSupportedTransactionVersion":0 - } - ] -}' - -# Result -{ - "jsonrpc": "2.0", - "result": { - "blockTime": 1665070281, - "meta": { - "err": null, - "fee": 5000, - "innerInstructions": [], - "logMessages": [ - "Program 11111111111111111111111111111111 invoke [1]", - "Program 11111111111111111111111111111111 success" - ], - "postBalances": [ - 1110663066, - 1, - 1040000000 - ], - "postTokenBalances": [], - "preBalances": [ - 1120668066, - 1, - 1030000000 - ], - "preTokenBalances": [], - "rewards": [], - "status": { - "Ok": null - } - }, - "slot": 166974442, - "transaction": { - "message": { - "accountKeys": [ - { - "pubkey": "9aE476sH92Vz7DMPyq5WLPkrKWivxeuTKEFKd2sZZcde", - "signer": true, - "source": "transaction", - "writable": true - }, - { - "pubkey": "11111111111111111111111111111111", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o", - "signer": false, - "source": "lookupTable", - "writable": true - } - ], - "addressTableLookups": [ - { - "accountKey": "4syr5pBaboZy4cZyF6sys82uGD7jEvoAP2ZMaoich4fZ", - "readonlyIndexes": [], - "writableIndexes": [ - 3 - ] - } - ], - "instructions": [ - { - "parsed": { - "info": { - "destination": "G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o", - "lamports": 10000000, - "source": "9aE476sH92Vz7DMPyq5WLPkrKWivxeuTKEFKd2sZZcde" - }, - "type": "transfer" - }, - "program": "system", - "programId": "11111111111111111111111111111111" - } - ], - "recentBlockhash": "BhhivDNgoy4L5tLtHb1s3TP19uUXqKiy4FfUR34d93eT" - }, - "signatures": [ - "2CxNRsyRT7y88GBwvAB3hRg8wijMSZh3VNYXAdUesGSyvbRJbRR2q9G1KSEpQENmXHmmMLHiXumw4dp8CvzQMjrM" - ] - }, - "version": 0 - }, - "id": 1 -} -``` - -## Sending Withdrawals - -To accommodate a user's request to withdraw SOL, you must generate a Solana -transfer transaction, and send it to the api node to be forwarded to your -cluster. - -### Synchronous - -Sending a synchronous transfer to the Solana cluster allows you to easily ensure -that a transfer is successful and finalized by the cluster. - -Solana's command-line tool offers a simple command, `solana transfer`, to -generate, submit, and confirm transfer transactions. By default, this method -will wait and track progress on stderr until the transaction has been finalized -by the cluster. If the transaction fails, it will report any transaction errors. - -```bash -solana transfer --allow-unfunded-recipient --keypair --url http://localhost:8899 -``` - -The [Solana Javascript SDK](https://github.com/solana-labs/solana-web3.js) -offers a similar approach for the JS ecosystem. Use the `SystemProgram` to build -a transfer transaction, and submit it using the `sendAndConfirmTransaction` -method. - -### Asynchronous - -For greater flexibility, you can submit withdrawal transfers asynchronously. In -these cases, it is your responsibility to verify that the transaction succeeded -and was finalized by the cluster. - -**Note:** Each transaction contains a [recent -blockhash](developing/programming-model/transactions.md#blockhash-format) to -indicate its liveness. It is **critical** to wait until this blockhash expires -before retrying a withdrawal transfer that does not appear to have been -confirmed or finalized by the cluster. Otherwise, you risk a double spend. See -more on [blockhash expiration](#blockhash-expiration) below. - -First, get a recent blockhash using the [`getFees`](../api/http#getfees) endpoint or the CLI command: - -```bash -solana fees --url http://localhost:8899 -``` - -In the command-line tool, pass the `--no-wait` argument to send a transfer -asynchronously, and include your recent blockhash with the `--blockhash` argument: - -```bash -solana transfer --no-wait --allow-unfunded-recipient --blockhash --keypair --url http://localhost:8899 -``` - -You can also build, sign, and serialize the transaction manually, and fire it off to -the cluster using the JSON-RPC [`sendTransaction`](../api/http#sendtransaction) endpoint. - -#### Transaction Confirmations & Finality - -Get the status of a batch of transactions using the -[`getSignatureStatuses`](../api/http#getsignaturestatuses) JSON-RPC endpoint. -The `confirmations` field reports how many -[confirmed blocks](../terminology.md#confirmed-block) have elapsed since the -transaction was processed. If `confirmations: null`, it is [finalized](../terminology.md#finality). - -```bash -curl localhost:8899 -X POST -H "Content-Type: application/json" -d '{ - "jsonrpc":"2.0", - "id":1, - "method":"getSignatureStatuses", - "params":[ - [ - "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW", - "5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7" - ] - ] -}' - -# Result -{ - "jsonrpc": "2.0", - "result": { - "context": { - "slot": 82 - }, - "value": [ - { - "slot": 72, - "confirmations": 10, - "err": null, - "status": { - "Ok": null - } - }, - { - "slot": 48, - "confirmations": null, - "err": null, - "status": { - "Ok": null - } - } - ] - }, - "id": 1 -} -``` - -#### Blockhash Expiration - -You can check whether a particular blockhash is still valid by sending a -[`getFeeCalculatorForBlockhash`](../api/http#getfeecalculatorforblockhash) -request with the blockhash as a parameter. If the response value is `null`, the -blockhash is expired, and the withdrawal transaction using that blockhash should -never succeed. - -### Validating User-supplied Account Addresses for Withdrawals - -As withdrawals are irreversible, it may be a good practice to validate a -user-supplied account address before authorizing a withdrawal in order to -prevent accidental loss of user funds. - -#### Basic verification - -Solana addresses a 32-byte array, encoded with the bitcoin base58 alphabet. This -results in an ASCII text string matching the following regular expression: - -``` -[1-9A-HJ-NP-Za-km-z]{32,44} -``` - -This check is insufficient on its own as Solana addresses are not checksummed, so -typos cannot be detected. To further validate the user's input, the string can be -decoded and the resulting byte array's length confirmed to be 32. However, there -are some addresses that can decode to 32 bytes despite a typo such as a single -missing character, reversed characters and ignored case - -#### Advanced verification - -Due to the vulnerability to typos described above, it is recommended that the -balance be queried for candidate withdraw addresses and the user prompted to -confirm their intentions if a non-zero balance is discovered. - -#### Valid ed25519 pubkey check - -The address of a normal account in Solana is a Base58-encoded string of a -256-bit ed25519 public key. Not all bit patterns are valid public keys for the -ed25519 curve, so it is possible to ensure user-supplied account addresses are -at least correct ed25519 public keys. - -#### Java - -Here is a Java example of validating a user-supplied address as a valid ed25519 -public key: - -The following code sample assumes you're using the Maven. - -`pom.xml`: - -```xml - - ... - - spring - https://repo.spring.io/libs-release/ - - - -... - - - ... - - io.github.novacrypto - Base58 - 0.1.3 - - - cafe.cryptography - curve25519-elisabeth - 0.1.0 - - -``` - -```java -import io.github.novacrypto.base58.Base58; -import cafe.cryptography.curve25519.CompressedEdwardsY; - -public class PubkeyValidator -{ - public static boolean verifyPubkey(String userProvidedPubkey) - { - try { - return _verifyPubkeyInternal(userProvidedPubkey); - } catch (Exception e) { - return false; - } - } - - public static boolean _verifyPubkeyInternal(String maybePubkey) throws Exception - { - byte[] bytes = Base58.base58Decode(maybePubkey); - return !(new CompressedEdwardsY(bytes)).decompress().isSmallOrder(); - } -} -``` - -## Minimum Deposit & Withdrawal Amounts - -Every deposit and withdrawal of SOL must be greater or equal to the minimum -rent-exempt balance for the account at the wallet address (a basic SOL account -holding no data), currently: 0.000890880 SOL - -Similarly, every deposit account must contain at least this balance. - -```bash -curl localhost:8899 -X POST -H "Content-Type: application/json" -d '{ - "jsonrpc": "2.0", - "id": 1, - "method": "getMinimumBalanceForRentExemption", - "params": [0] -}' - -# Result -{"jsonrpc":"2.0","result":890880,"id":1} -``` - -## Supporting the SPL Token Standard - -[SPL Token](https://spl.solana.com/token) is the standard for wrapped/synthetic -token creation and exchange on the Solana blockchain. - -The SPL Token workflow is similar to that of native SOL tokens, but there are a -few differences which will be discussed in this section. - -### Token Mints - -Each _type_ of SPL Token is declared by creating a _mint_ account. This account -stores metadata describing token features like the supply, number of decimals, and -various authorities with control over the mint. Each SPL Token account references -its associated mint and may only interact with SPL Tokens of that type. - -### Installing the `spl-token` CLI Tool - -SPL Token accounts are queried and modified using the `spl-token` command line -utility. The examples provided in this section depend upon having it installed -on the local system. - -`spl-token` is distributed from Rust [crates.io](https://crates.io/crates/spl-token) -via the Rust `cargo` command line utility. The latest version of `cargo` can be -installed using a handy one-liner for your platform at [rustup.rs](https://rustup.rs). -Once `cargo` is installed, `spl-token` can be obtained with the following command: - -``` -cargo install spl-token-cli -``` - -You can then check the installed version to verify - -``` -spl-token --version -``` - -Which should result in something like - -```text -spl-token-cli 2.0.1 -``` - -### Account Creation - -SPL Token accounts carry additional requirements that native System Program -accounts do not: - -1. SPL Token accounts must be created before an amount of tokens can be - deposited. Token accounts can be created explicitly with the - `spl-token create-account` command, or implicitly by the - `spl-token transfer --fund-recipient ...` command. -1. SPL Token accounts must remain [rent-exempt](developing/programming-model/accounts.md#rent-exemption) - for the duration of their existence and therefore require a small amount of - native SOL tokens be deposited at account creation. For SPL Token v2 accounts, - this amount is 0.00203928 SOL (2,039,280 lamports). - -#### Command Line - -To create an SPL Token account with the following properties: - -1. Associated with the given mint -1. Owned by the funding account's keypair - -``` -spl-token create-account -``` - -#### Example - -``` -$ spl-token create-account AkUFCWTXb3w9nY2n6SFJvBV6VwvFUCe4KBMCcgLsa2ir -Creating account 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV -Signature: 4JsqZEPra2eDTHtHpB4FMWSfk3UgcCVmkKkP7zESZeMrKmFFkDkNd91pKP3vPVVZZPiu5XxyJwS73Vi5WsZL88D7 -``` - -Or to create an SPL Token account with a specific keypair: - -``` -$ solana-keygen new -o token-account.json -$ spl-token create-account AkUFCWTXb3w9nY2n6SFJvBV6VwvFUCe4KBMCcgLsa2ir token-account.json -Creating account 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV -Signature: 4JsqZEPra2eDTHtHpB4FMWSfk3UgcCVmkKkP7zESZeMrKmFFkDkNd91pKP3vPVVZZPiu5XxyJwS73Vi5WsZL88D7 -``` - -### Checking an Account's Balance - -#### Command Line - -``` -spl-token balance -``` - -#### Example - -``` -$ solana balance 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV -0 -``` - -### Token Transfers - -The source account for a transfer is the actual token account that contains the -amount. - -The recipient address however can be a normal wallet account. If an associated -token account for the given mint does not yet exist for that wallet, the -transfer will create it provided that the `--fund-recipient` argument as -provided. - -#### Command Line - -``` -spl-token transfer --fund-recipient -``` - -#### Example - -``` -$ spl-token transfer 6B199xxzw3PkAm25hGJpjj3Wj3WNYNHzDAnt1tEqg5BN 1 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV -Transfer 1 tokens - Sender: 6B199xxzw3PkAm25hGJpjj3Wj3WNYNHzDAnt1tEqg5BN - Recipient: 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV -Signature: 3R6tsog17QM8KfzbcbdP4aoMfwgo6hBggJDVy7dZPVmH2xbCWjEj31JKD53NzMrf25ChFjY7Uv2dfCDq4mGFFyAj -``` - -### Depositing - -Since each `(wallet, mint)` pair requires a separate account on chain. It is -recommended that the addresses for these accounts be derived from SOL deposit -wallets using the -[Associated Token Account](https://spl.solana.com/associated-token-account) (ATA) -scheme and that _only_ deposits from ATA addresses be accepted. - -Monitoring for deposit transactions should follow the [block polling](#poll-for-blocks) -method described above. Each new block should be scanned for successful -transactions referencing user token-account derived addresses. The -`preTokenBalance` and `postTokenBalance` fields from the transaction's metadata -must then be used to determine the effective balance change. These fields will -identify the token mint and account owner (main wallet address) of the affected -account. - -Note that if a receiving account is created during the transaction, it will have no -`preTokenBalance` entry as there is no existing account state. In this -case, the initial balance can be assumed to be zero. - -### Withdrawing - -The withdrawal address a user provides must be the that of their SOL wallet. - -Before executing a withdrawal [transfer](#token-transfers), -the exchange should check the address as -[described above](#validating-user-supplied-account-addresses-for-withdrawals). -Additionally this address must be owned by the System Program and have no -account data. If the address has no SOL balance, user confirmation should be -obtained before proceeding with the withdrawal. All other withdrawal addresses -must be rejected. - -From the withdrawal address, the [Associated Token Account](https://spl.solana.com/associated-token-account) -(ATA) for the correct mint is derived and the transfer issued to that account via a -[TransferChecked](https://github.com/solana-labs/solana-program-library/blob/fc0d6a2db79bd6499f04b9be7ead0c400283845e/token/program/src/instruction.rs#L268) -instruction. Note that it is possible that the ATA address does not yet exist, at which point the -exchange should fund the account on behalf of the user. For SPL Token v2 -accounts, funding the withdrawal account will require 0.00203928 SOL (2,039,280 -lamports). - -Template `spl-token transfer` command for a withdrawal: - -``` -$ spl-token transfer --fund-recipient -``` - -### Other Considerations - -#### Freeze Authority - -For regulatory compliance reasons, an SPL Token issuing entity may optionally -choose to hold "Freeze Authority" over all accounts created in association with -its mint. This allows them to [freeze](https://spl.solana.com/token#freezing-accounts) -the assets in a given account at will, rendering the account unusable until thawed. -If this feature is in use, the freeze authority's pubkey will be registered in -the SPL Token's mint account. - -## Testing the Integration - -Be sure to test your complete workflow on Solana devnet and testnet -[clusters](../clusters.md) before moving to production on mainnet-beta. Devnet -is the most open and flexible, and ideal for initial development, while testnet -offers more realistic cluster configuration. Both devnet and testnet support a faucet, -run `solana airdrop 1` to obtain some devnet or testnet SOL for development and testing. diff --git a/docs/src/integrations/retrying-transactions.md b/docs/src/integrations/retrying-transactions.md deleted file mode 100644 index c2d7ff24be..0000000000 --- a/docs/src/integrations/retrying-transactions.md +++ /dev/null @@ -1,336 +0,0 @@ ---- -title: Retrying Transactions ---- - -# Retrying Transactions - -On some occasions, a seemingly valid transaction may be dropped before it is -included in a block. This most often occurs during periods of network -congestion, when an RPC node fails to rebroadcast the transaction to the -[leader](../terminology#leader). To an end-user, it may -appear as if their transaction disappears entirely. While RPC nodes are equipped -with a generic rebroadcasting algorithm, application developers are also capable -of developing their own custom rebroadcasting logic. - -## Facts - -:::note -Fact Sheet - -- RPC nodes will attempt to rebroadcast transactions using a generic algorithm -- Application developers can implement their own custom rebroadcasting logic -- Developers should take advantage of the `maxRetries` parameter on the - `sendTransaction` JSON-RPC method -- Developers should enable preflight checks to raise errors before transactions - are submitted -- Before re-signing any transaction, it is **very important** to ensure that the - initial transaction’s blockhash has expired - -::: - -## The Journey of a Transaction - -### How Clients Submit Transactions - -In Solana, there is no concept of a mempool. All transactions, whether they are -initiated programmatically or by an end-user, are efficiently routed to leaders -so that they can be processed into a block. There are two main ways in which a -transaction can be sent to leaders: - -1. By proxy via an RPC server and the - [sendTransaction](../api/http#sendtransaction) - JSON-RPC method -2. Directly to leaders via a - [TPU Client](https://docs.rs/solana-client/1.7.3/solana_client/tpu_client/index.html) - -The vast majority of end-users will submit transactions via an RPC server. When -a client submits a transaction, the receiving RPC node will in turn attempt to -broadcast the transaction to both the current and next leaders. Until the -transaction is processed by a leader, there is no record of the transaction -outside of what the client and the relaying RPC nodes are aware of. In the case -of a TPU client, rebroadcast and leader forwarding is handled entirely by the -client software. - -![Transaction Journey](../../static/img/rt-tx-journey.png) - - - -### How RPC Nodes Broadcast Transactions - -After an RPC node receives a transaction via `sendTransaction`, it will convert -the transaction into a -[UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol) packet before -forwarding it to the relevant leaders. UDP allows validators to quickly -communicate with one another, but does not provide any guarantees regarding -transaction delivery. - -Because Solana’s leader schedule is known in advance of every -[epoch](../terminology#epoch) (~2 days), an RPC node will -broadcast its transaction directly to the current and next leaders. This is in -contrast to other gossip protocols such as Ethereum that propagate transactions -randomly and broadly across the entire network. By default, RPC nodes will try -to forward transactions to leaders every two seconds until either the -transaction is finalized or the transaction’s blockhash expires (150 blocks or -~1 minute 19 seconds as of the time of this writing). If the outstanding -rebroadcast queue size is greater than -[10,000 transactions](https://github.com/solana-labs/solana/blob/bfbbc53dac93b3a5c6be9b4b65f679fdb13e41d9/send-transaction-service/src/send_transaction_service.rs#L20), -newly submitted transactions are dropped. There are command-line -[arguments](https://github.com/solana-labs/solana/blob/bfbbc53dac93b3a5c6be9b4b65f679fdb13e41d9/validator/src/main.rs#L1172) -that RPC operators can adjust to change the default behavior of this retry -logic. - -When an RPC node broadcasts a transaction, it will attempt to forward the -transaction to a leader’s -[Transaction Processing Unit (TPU)](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/core/src/validator.rs#L867). -The TPU processes transactions in five distinct phases: - -- [Fetch Stage](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/core/src/fetch_stage.rs#L21) -- [SigVerify Stage](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/core/src/tpu.rs#L91) -- [Banking Stage](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/core/src/banking_stage.rs#L249) -- [Proof of History Service](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/poh/src/poh_service.rs) -- [Broadcast Stage](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/core/src/tpu.rs#L136) - -![TPU Overview](../../static/img/rt-tpu-jito-labs.png) - -Of these five phases, the Fetch Stage is responsible for receiving transactions. -Within the Fetch Stage, validators will categorize incoming transactions -according to three ports: - -- [tpu](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/gossip/src/contact_info.rs#L27) - handles regular transactions such as token transfers, NFT mints, and program - instructions -- [tpu_vote](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/gossip/src/contact_info.rs#L31) - focuses exclusively on voting transactions -- [tpu_forwards](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/gossip/src/contact_info.rs#L29) - forwards unprocessed packets to the next leader if the current leader is - unable to process all transactions - -For more information on the TPU, please refer to -[this excellent writeup by Jito Labs](https://jito-labs.medium.com/solana-validator-101-transaction-processing-90bcdc271143). - -## How Transactions Get Dropped - -Throughout a transaction’s journey, there are a few scenarios in which the -transaction can be unintentionally dropped from the network. - -### Before a transaction is processed - -If the network drops a transaction, it will most likely do so before the -transaction is processed by a leader. UDP -[packet loss](https://en.wikipedia.org/wiki/Packet_loss) is the simplest reason -why this might occur. During times of intense network load, it’s also possible -for validators to become overwhelmed by the sheer number of transactions -required for processing. While validators are equipped to forward surplus -transactions via `tpu_forwards`, there is a limit to the amount of data that can -be -[forwarded](https://github.com/solana-labs/solana/blob/master/core/src/banking_stage.rs#L389). -Furthermore, each forward is limited to a single hop between validators. That -is, transactions received on the `tpu_forwards` port are not forwarded on to -other validators. - -There are also two lesser known reasons why a transaction may be dropped before -it is processed. The first scenario involves transactions that are submitted via -an RPC pool. Occasionally, part of the RPC pool can be sufficiently ahead of the -rest of the pool. This can cause issues when nodes within the pool are required -to work together. In this example, the transaction’s -[recentBlockhash](../developing/programming-model/transactions#recent-blockhash) -is queried from the advanced part of the pool (Backend A). When the transaction -is submitted to the lagging part of the pool (Backend B), the nodes will not -recognize the advanced blockhash and will drop the transaction. This can be -detected upon transaction submission if developers enable -[preflight checks](../api/http#sendtransaction) -on `sendTransaction`. - -![Dropped via RPC Pool](../../static/img/rt-dropped-via-rpc-pool.png) - -Temporarily network forks can also result in dropped transactions. If a -validator is slow to replay its blocks within the Banking Stage, it may end up -creating a minority fork. When a client builds a transaction, it’s possible for -the transaction to reference a `recentBlockhash` that only exists on the -minority fork. After the transaction is submitted, the cluster can then switch -away from its minority fork before the transaction is processed. In this -scenario, the transaction is dropped due to the blockhash not being found. - -![Dropped due to Minority Fork (Before Processed)](../../static/img/rt-dropped-minority-fork-pre-process.png) - -### After a transaction is processed and before it is finalized - -In the event a transaction references a `recentBlockhash` from a minority fork, -it’s still possible for the transaction to be processed. In this case, however, -it would be processed by the leader on the minority fork. When this leader -attempts to share its processed transactions with the rest of the network, it -would fail to reach consensus with the majority of validators that do not -recognize the minority fork. At this time, the transaction would be dropped -before it could be finalized. - -![Dropped due to Minority Fork (After Processed)](../../static/img/rt-dropped-minority-fork-post-process.png) - -## Handling Dropped Transactions - -While RPC nodes will attempt to rebroadcast transactions, the algorithm they -employ is generic and often ill-suited for the needs of specific applications. -To prepare for times of network congestion, application developers should -customize their own rebroadcasting logic. - -### An In-Depth Look at sendTransaction - -When it comes to submitting transactions, the `sendTransaction` RPC method is -the primary tool available to developers. `sendTransaction` is only responsible -for relaying a transaction from a client to an RPC node. If the node receives -the transaction, `sendTransaction` will return the transaction id that can be -used to track the transaction. A successful response does not indicate whether -the transaction will be processed or finalized by the cluster. - -:::note - -### Request Parameters - -- `transaction`: `string` - fully-signed Transaction, as encoded string -- (optional) `configuration object`: `object` - - `skipPreflight`: `boolean` - if true, skip the preflight transaction checks - (default: false) - - (optional) `preflightCommitment`: `string` - - [Commitment](../api/http#configuring-state-commitment) - level to use for preflight simulations against the bank slot (default: - "finalized"). - - (optional) `encoding`: `string` - Encoding used for the transaction data. - Either "base58" (slow), or "base64". (default: "base58"). - - (optional) `maxRetries`: `usize` - Maximum number of times for the RPC node - to retry sending the transaction to the leader. If this parameter is not - provided, the RPC node will retry the transaction until it is finalized or - until the blockhash expires. - -Response - -- `transaction id`: `string` - First transaction signature embedded in the - transaction, as base-58 encoded string. This transaction id can be used with - [`getSignatureStatuses`](../api/http#getsignaturestatuses) - to poll for status updates. - -::: - -## Customizing Rebroadcast Logic - -In order to develop their own rebroadcasting logic, developers should take -advantage of `sendTransaction`’s `maxRetries` parameter. If provided, -`maxRetries` will override an RPC node’s default retry logic, allowing -developers to manually control the retry process -[within reasonable bounds](https://github.com/solana-labs/solana/blob/98707baec2385a4f7114d2167ef6dfb1406f954f/validator/src/main.rs#L1258-L1274). - -A common pattern for manually retrying transactions involves temporarily storing -the `lastValidBlockHeight` that comes from -[getLatestBlockhash](../api/http#getlatestblockhash). -Once stashed, an application can then -[poll the cluster’s blockheight](../api/http#getblockheight) -and manually retry the transaction at an appropriate interval. In times of -network congestion, it’s advantageous to set `maxRetries` to 0 and manually -rebroadcast via a custom algorithm. While some applications may employ an -[exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff) -algorithm, others such as [Mango](https://www.mango.markets/) opt to -[continuously resubmit](https://github.com/blockworks-foundation/mango-ui/blob/b6abfc6c13b71fc17ebbe766f50b8215fa1ec54f/src/utils/send.tsx#L713) -transactions at a constant interval until some timeout has occurred. - -```ts -import { - Keypair, - Connection, - LAMPORTS_PER_SOL, - SystemProgram, - Transaction, -} from "@solana/web3.js"; -import * as nacl from "tweetnacl"; - -const sleep = async (ms: number) => { - return new Promise((r) => setTimeout(r, ms)); -}; - -(async () => { - const payer = Keypair.generate(); - const toAccount = Keypair.generate().publicKey; - - const connection = new Connection("http://127.0.0.1:8899", "confirmed"); - - const airdropSignature = await connection.requestAirdrop( - payer.publicKey, - LAMPORTS_PER_SOL, - ); - - await connection.confirmTransaction({ signature: airdropSignature }); - - const blockhashResponse = await connection.getLatestBlockhashAndContext(); - const lastValidBlockHeight = blockhashResponse.context.slot + 150; - - const transaction = new Transaction({ - feePayer: payer.publicKey, - blockhash: blockhashResponse.value.blockhash, - lastValidBlockHeight: lastValidBlockHeight, - }).add( - SystemProgram.transfer({ - fromPubkey: payer.publicKey, - toPubkey: toAccount, - lamports: 1000000, - }), - ); - const message = transaction.serializeMessage(); - const signature = nacl.sign.detached(message, payer.secretKey); - transaction.addSignature(payer.publicKey, Buffer.from(signature)); - const rawTransaction = transaction.serialize(); - let blockheight = await connection.getBlockHeight(); - - while (blockheight < lastValidBlockHeight) { - connection.sendRawTransaction(rawTransaction, { - skipPreflight: true, - }); - await sleep(500); - blockheight = await connection.getBlockHeight(); - } -})(); -``` - -When polling via `getLatestBlockhash`, applications should specify their -intended -[commitment](../api/http#configuring-state-commitment) -level. By setting its commitment to `confirmed` (voted on) or `finalized` (~30 -blocks after `confirmed`), an application can avoid polling a blockhash from a -minority fork. - -If an application has access to RPC nodes behind a load balancer, it can also -choose to divide its workload amongst specific nodes. RPC nodes that serve -data-intensive requests such as -[getProgramAccounts](https://solanacookbook.com/guides/get-program-accounts.html) -may be prone to falling behind and can be ill-suited for also forwarding -transactions. For applications that handle time-sensitive transactions, it may -be prudent to have dedicated nodes that only handle `sendTransaction`. - -### The Cost of Skipping Preflight - -By default, `sendTransaction` will perform three preflight checks prior to -submitting a transaction. Specifically, `sendTransaction` will: - -- Verify that all signatures are valid -- Check that the referenced blockhash is within the last 150 blocks -- Simulate the transaction against the bank slot specified by the - `preflightCommitment` - -In the event that any of these three preflight checks fail, `sendTransaction` -will raise an error prior to submitting the transaction. Preflight checks can -often be the difference between losing a transaction and allowing a client to -gracefully handle an error. To ensure that these common errors are accounted -for, it is recommended that developers keep `skipPreflight` set to `false`. - -### When to Re-Sign Transactions - -Despite all attempts to rebroadcast, there may be times in which a client is -required to re-sign a transaction. Before re-signing any transaction, it is -**very important** to ensure that the initial transaction’s blockhash has -expired. If the initial blockhash is still valid, it is possible for both -transactions to be accepted by the network. To an end-user, this would appear as -if they unintentionally sent the same transaction twice. - -In Solana, a dropped transaction can be safely discarded once the blockhash it -references is older than the `lastValidBlockHeight` received from -`getLatestBlockhash`. Developers should keep track of this -`lastValidBlockHeight` by querying -[`getEpochInfo`](../api/http#getepochinfo) -and comparing with `blockHeight` in the response. Once a blockhash is -invalidated, clients may re-sign with a newly-queried blockhash. diff --git a/docs/src/introduction.md b/docs/src/introduction.md deleted file mode 100644 index 4a1e9c1a5e..0000000000 --- a/docs/src/introduction.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Introduction ---- - -## What is Solana? - -Solana is an open source project implementing a new, high-performance, permissionless blockchain. The Solana Foundation is based in Geneva, Switzerland and maintains the open source project. - -## Why Solana? - -It is possible for a centralized database to process 710,000 transactions per second on a standard gigabit network if the transactions are, on average, no more than 176 bytes. A centralized database can also replicate itself and maintain high availability without significantly compromising that transaction rate using the distributed system technique known as Optimistic Concurrency Control [\[H.T.Kung, J.T.Robinson (1981)\]](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.65.4735). At Solana, we are demonstrating that these same theoretical limits apply just as well to blockchain on an adversarial network. The key ingredient? Finding a way to share time when nodes cannot rely upon one another. Once nodes can rely upon time, suddenly ~40 years of distributed systems research becomes applicable to blockchain! - -> Perhaps the most striking difference between algorithms obtained by our method and ones based upon timeout is that using timeout produces a traditional distributed algorithm in which the processes operate asynchronously, while our method produces a globally synchronous one in which every process does the same thing at (approximately) the same time. Our method seems to contradict the whole purpose of distributed processing, which is to permit different processes to operate independently and perform different functions. However, if a distributed system is really a single system, then the processes must be synchronized in some way. Conceptually, the easiest way to synchronize processes is to get them all to do the same thing at the same time. Therefore, our method is used to implement a kernel that performs the necessary synchronization--for example, making sure that two different processes do not try to modify a file at the same time. Processes might spend only a small fraction of their time executing the synchronizing kernel; the rest of the time, they can operate independently--e.g., accessing different files. This is an approach we have advocated even when fault-tolerance is not required. The method's basic simplicity makes it easier to understand the precise properties of a system, which is crucial if one is to know just how fault-tolerant the system is. [\[L.Lamport (1984)\]](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.71.1078) - -Furthermore, and much to our surprise, it can be implemented using a mechanism that has existed in Bitcoin since day one. The Bitcoin feature is called nLocktime and it can be used to postdate transactions using block height instead of a timestamp. As a Bitcoin client, you would use block height instead of a timestamp if you don't rely upon the network. Block height turns out to be an instance of what's being called a Verifiable Delay Function in cryptography circles. It's a cryptographically secure way to say time has passed. In Solana, we use a far more granular verifiable delay function, a SHA 256 hash chain, to checkpoint the ledger and coordinate consensus. With it, we implement Optimistic Concurrency Control and are now well en route towards that theoretical limit of 710,000 transactions per second. - -## Documentation Overview - -The Solana docs describe the Solana open source project, a blockchain built from the ground up for scale. They cover why Solana is useful, how to use it, how it works, and why it will continue to work long after the company Solana closes its doors. The goal of the Solana architecture is to demonstrate there exists a set of software algorithms that when used in combination to implement a blockchain, removes software as a performance bottleneck, allowing transaction throughput to scale proportionally with network bandwidth. The architecture goes on to satisfy all three desirable properties of a proper blockchain: it is scalable, secure and decentralized. - -The architecture describes a theoretical upper bound of 710 thousand transactions per second \(tps\) on a standard gigabit network and 28.4 million tps on 40 gigabit. Furthermore, the architecture supports safe, concurrent execution of programs authored in general-purpose programming languages such as C or Rust. - -## What is a Solana Cluster? - -A cluster is a set of computers that work together and can be viewed from the outside as a single system. A Solana cluster is a set of independently owned computers working together \(and sometimes against each other\) to verify the output of untrusted, user-submitted programs. A Solana cluster can be utilized any time a user wants to preserve an immutable record of events in time or programmatic interpretations of those events. One use is to track which of the computers did meaningful work to keep the cluster running. Another use might be to track the possession of real-world assets. In each case, the cluster produces a record of events called the ledger. It will be preserved for the lifetime of the cluster. As long as someone somewhere in the world maintains a copy of the ledger, the output of its programs \(which may contain a record of who possesses what\) will forever be reproducible, independent of the organization that launched it. - -## What are SOLs? - -A SOL is the name of Solana's native token, which can be passed to nodes in a Solana cluster in exchange for running an on-chain program or validating its output. The system may perform micropayments of fractional SOLs, which are called _lamports_. They are named in honor of Solana's biggest technical influence, [Leslie Lamport](https://en.wikipedia.org/wiki/Leslie_Lamport). A lamport has a value of 0.000000001 SOL. - -## Disclaimer - -All claims, content, designs, algorithms, estimates, roadmaps, specifications, and performance measurements described in this project are done with the author's best effort. It is up to the reader to check and validate their accuracy and truthfulness. Furthermore, nothing in this project constitutes a solicitation for investment. diff --git a/docs/src/learn/state-compression.md b/docs/src/learn/state-compression.md deleted file mode 100644 index 993544944b..0000000000 --- a/docs/src/learn/state-compression.md +++ /dev/null @@ -1,334 +0,0 @@ ---- -title: State Compression -description: - 'State Compression is the method of cheaply and securely storing - "fingerprints" of off-chain data in the Solana leger, instead of expensive - accounts.' ---- - -On Solana, [State Compression](./state-compression.md) is the method of creating -a "fingerprint" (or hash) of off-chain data and storing this fingerprint -on-chain for secure verification. Effectively using the security of the Solana -ledger to securely validate off-chain data, verifying it has not been tampered -with. - -This method of "compression" allows Solana programs and dApps to use cheap -blockchain [ledger](./../terminology.md#ledger) space, instead of the more -expensive [account](./../terminology.md#account) space, to securely store data. - -This is accomplished by using a special binary tree structure, known as a -[concurrent merkle tree](#what-is-a-concurrent-merkle-tree), to create a hash of -each piece of data (called a `leaf`), hashing those together, and only storing -this final hash on-chain. - -## What is State Compression? - -In simple terms, state compression uses "**_tree_**" structures to -cryptographically hash off-chain data together, in a deterministic way, to -compute a single final hash that gets stored on-chain. - -These _trees_ are created in this "_deterministic_" process by: - -- taking any piece of data -- creating a hash of this data -- storing this hash as a `leaf` the bottom of the tree -- each `leaf` pair is then hash together, creating a `branch` -- each `branch` is then hash together -- continually climbing the tree and hashing adjacent branches together -- once at the top of the tree, a final `root hash` is produced - -This `root hash` is then stored on chain, as a verifiable **_proof_** of all of -the data within every leaf. Allowing anyone to cryptographically verify all the -off-chain data within the tree, while only actually storing a **minimal** amount -of data on-chain. Therefore, significantly reducing the cost to store/prove -large amounts of data due to this "state compression". - -## Merkle trees and concurrent merkle trees - -Solana's state compression used a special type of -[merkle tree](#what-is-a-merkle-tree) that allows for multiple changes to any -given tree to happen, while still maintaining the integrity and validity of the -tree. - -This special tree, known as a -"[concurrent merkle tree](#what-is-a-concurrent-merkle-tree)", effectively -retains a "changelog" of the tree on-chain. Allowing for multiple rapid changes -to the same tree (i.e. all in the same block), before a proof is invalidated. - -### What is a merkle tree? - -A [merkle tree](https://en.wikipedia.org/wiki/merkle_tree), sometimes called a -"hash tree", is a hash based binary tree structure where each `leaf` node is -represented as a cryptographic hash of its inner data. And every node that is -**not** a leaf, called a `branch`, is represented as a hash of its child leaf -hashes. - -Each branch is then also hashed together, climbing the tree, until eventually -only a single hash remains. This final hash, called the `root hash` or "root", -can then be used in combination with a "proof path" to verify any piece of data -stored within a leaf node. - -Once a final `root hash` has been computed, any piece of data stored within a -`leaf` node can be verified by rehashing the specific leaf's data and the hash -label of each adjacent branch climbing the tree (known as the `proof` or "proof -path"). Comparing this "rehash" to the `root hash` is the verification of the -underlying leaf data. If they match, the data is verified accurate. If they do -not match, the leaf data was changed. - -Whenever desired, the original leaf data can be changed by simply hashing the -**new leaf** data and recomputing the root hash in the same manner of the -original root. This **new root hash** is then used to verify any of the data, -and effectively invalidates the previous root hash and previous proof. -Therefore, each change to these _traditional merkle trees_ are required to be -performed in series. - -:::info - -This process of changing leaf data, and computing a new root hash can be a -**very common** thing when using merkle trees! While it is one of the design -points of the tree, it can result in one of the most notable drawbacks: rapid -changes. - -::: - -### What is a Concurrent merkle tree? - -In high throughput applications, like within the -[Solana runtime](/src/validator/runtime.md), requests to change an on-chain -_traditional merkle tree_ could be received by validators in relatively rapid -succession (e.g. within the same slot). Each leaf data change would still be -required to performed in series. Resulting in each subsequent request for change -to fail, due to the root hash and proof being invalidated by the previous change -request in the slot. - -Enter, Concurrent merkle trees. - -A **Concurrent merkle tree** stores a **secure changelog** of the most recent -changes, their root hash, and the proof to derive it. This changelog "buffer" is -stored on-chain in an account specific to each tree, with a maximum number of -changelog "records" (aka `maxBufferSize`). - -When multiple leaf data change requests are received by validators in the same -slot, the on-chain _concurrent merkle tree_ can use this "changelog buffer" as a -source of truth for more acceptable proofs. Effectively allowing for up to -`maxBufferSize` changes to the same tree in the same slot. Significantly -boosting throughput. - -## Sizing a concurrent merkle tree - -When creating one of these on-chain trees, there are 3 values that will -determine the size of your tree, the cost to create your tree, and the number of -concurrent changes to your tree: - -1. max depth -2. max buffer size -3. canopy depth - -### Max depth - -The "max depth" of a tree is the **maximum number** of hops to get from any data -`leaf` to the `root` of the tree. - -Since merkle trees are binary trees, every leaf is connected to **only one** -other leaf; existing as a `leaf pair`. - -Therefore, the `maxDepth` of a tree is used to determine the maximum number of -nodes (aka pieces of data or `leafs`) to store within the tree using a simple -calculation: - -``` -nodes_count = 2 ^ maxDepth -``` - -Since a trees depth must be set at tree creation, you must decide how many -pieces of data you want your tree to store. Then using the simple calculation -above, you can determine the lowest `maxDepth` to store your data. - -#### Example 1: minting 100 nfts - -If you wanted to create a tree to store 100 compressed nfts, we will need a -minimum of "100 leafs" or "100 nodes". - -``` -// maxDepth=6 -> 64 nodes -2^6 = 64 - -// maxDepth=7 -> 128 nodes -2^7 = 128 -``` - -We must use a `maxDepth` of `7` to ensure we can store all of our data. - -#### Example 2: minting 15000 nfts - -If you wanted to create a tree to store 15000 compressed nfts, we will need a -minimum of "15000 leafs" or "15000 nodes". - -``` -// maxDepth=13 -> 8192 nodes -2^13 = 8192 - -// maxDepth=14 -> 16384 nodes -2^14 = 16384 -``` - -We must use a `maxDepth` of `14` to ensure we can store all of our data. - -#### The higher the max depth, the higher the cost - -The `maxDepth` value will be one of the primary drivers of cost when creating a -tree since you will pay this cost upfront at tree creation. The higher the max -tree depth depth, the more data fingerprints (aka hashes) you can store, the -higher the cost. - -### Max buffer size - -The "max buffer size" is effectively the maximum number of changes that can -occur on a tree, with the `root hash` still being valid. - -Due to the root hash effectively being a single hash of all leaf data, changing -any single leaf would invalidate the proof needed for all subsequent attempts to -change any leaf of a regular tree. - -But with a [concurrent tree](#what-is-a-concurrent-merkle-tree), there is -effectively a changelog of updates for these proofs. This changelog buffer is -sized and set at tree creation via this `maxBufferSize` value. - -### Canopy depth - -The "canopy depth", sometimes called the canopy size, is the number of proof -nodes that are cached/stored on-chain for any given proof path. - -When performing an update action on a `leaf`, like transferring ownership (e.g. -selling a compressed NFT), the **complete** proof path must be used to verify -original ownership of the leaf and therefore allow for the update action. This -verification is performed using the **complete** proof path to correctly compute -the current `root hash` (or any cached `root hash` via the on-chain "concurrent -buffer"). - -The larger a tree's max depth is, the more proof nodes are required to perform -this verification. For example, if your max depth is `14`, there are `14` total -proof nodes required to be used to verify. As a tree gets larger, the complete -proof path gets larger. - -Normally, each of these proof nodes would be required to be included within each -tree update transaction. Since each proof node value takes up `32 bytes` in a -transaction (similar to providing a Public Key), larger trees would very quickly -exceed the maximum transaction size limit. - -Enter the canopy. The canopy enables storing a set number of proof nodes on -chain (for any given proof path). Allowing for less proof nodes to be included -within each update transactions, therefore keeping the overall transaction size -below the limit. - -For example, a tree with a max depth of `14` would require `14` total proof -nodes. With a canopy of `10`, only `4` proof nodes are required to be submitted -per update transaction. - -#### The larger the canopy depth value, the higher the cost - -The `canopyDepth` value is also a primary factor of cost when creating a tree -since you will pay this cost upfront at tree creation. The higher the canopy -depth, the more data proof nodes are stored on chain, the higher the cost. - -#### Smaller canopy limits composability - -While a tree's creation costs are higher with a higher canopy, having a lower -`canopyDepth` will require more proof nodes to be included within each update -transaction. The more nodes required to be submitted, the larger the transaction -size, and therefore the easier it is to exceed the transaction size limits. - -This will also be the case for any other Solana program or dApp that attempts to -interact with your tree/leafs. If your tree requires too many proof nodes -(because of a low canopy depth), then any other additional actions another -on-chain program **could** offer will be **limited** by their specific -instruction size plus your proof node list size. Limiting composability, and -potential additional utility for your specific tree. - -For example, if your tree is being used for compressed NFTs and has a very low -canopy depth, an NFT marketplace may only be able to support simple NFTs -transfers. And not be able to support an on-chain bidding system. - -## Cost of creating a tree - -The cost of creating a concurrent merkle tree is based on the tree's size -parameters: `maxDepth`, `maxBufferSize`, and `canopyDepth`. These values are all -used to calculate the on-chain storage (in bytes) required for a tree to exist -on chain. - -Once the required space (in bytes) has been calculated, and using the -[`getMinimumBalanceForRentExemption`](/api/http#getminimumbalanceforrentexemption) -RPC method, request the cost (in lamports) to allocate this amount of bytes -on-chain. - -### Calculate tree cost in JavaScript - -Within the -[`@solana/spl-account-compression`](https://www.npmjs.com/package/@solana/spl-account-compression) -package, developers can use the -[`getConcurrentMerkleTreeAccountSize`](https://solana-labs.github.io/solana-program-library/account-compression/sdk/docs/modules/index.html#getConcurrentMerkleTreeAccountSize) -function to calculate the required space for a given tree size parameters. - -Then using the -[`getMinimumBalanceForRentExemption`](https://solana-labs.github.io/solana-web3.js/classes/Connection.html#getMinimumBalanceForRentExemption) -function to get the final cost (in lamports) to allocate the required space for -the tree on-chain. - -Then determine the cost in lamports to make an account of this size rent exempt, -similar to any other account creation. - -```ts -// calculate the space required for the tree -const requiredSpace = getConcurrentMerkleTreeAccountSize( - maxDepth, - maxBufferSize, - canopyDepth, -); - -// get the cost (in lamports) to store the tree on-chain -const storageCost = await connection.getMinimumBalanceForRentExemption( - requiredSpace, -); -``` - -### Example costs - -Listed below are several example costs, for different tree sizes, including how -many leaf nodes are possible for each: - -**Example #1: 16,384 nodes costing 0.222 SOL** - -- max depth of `14` and max buffer size of `64` -- maximum number of leaf nodes: `16,384` -- canopy depth of `0` costs approximately `0.222 SOL` to create - -**Example #2: 16,384 nodes costing 1.134 SOL** - -- max depth of `14` and max buffer size of `64` -- maximum number of leaf nodes: `16,384` -- canopy depth of `11` costs approximately `1.134 SOL` to create - -**Example #3: 1,048,576 nodes costing 1.673 SOL** - -- max depth of `20` and max buffer size of `256` -- maximum number of leaf nodes: `1,048,576` -- canopy depth of `10` costs approximately `1.673 SOL` to create - -**Example #4: 1,048,576 nodes costing 15.814 SOL** - -- max depth of `20` and max buffer size of `256` -- maximum number of leaf nodes: `1,048,576` -- canopy depth of `15` costs approximately `15.814 SOL` to create - -## Compressed NFTs - -Compressed NFTs are one of the most popular use cases for State Compression on -Solana. With compression, a one million NFT collection could be minted for -`~50 SOL`, vice `~12,000 SOL` for its uncompressed equivalent collection. - -:::info Developer Guide - -Read our developer guide for -[minting and transferring compressed NFTs](./../developing/guides/compressed-nfts). - -::: diff --git a/docs/src/operations/_category_.json b/docs/src/operations/_category_.json new file mode 100644 index 0000000000..a32cdd91fe --- /dev/null +++ b/docs/src/operations/_category_.json @@ -0,0 +1,10 @@ +{ + "position": 4, + "label": "Operating a Validator", + "collapsible": true, + "collapsed": true, + "link": { + "type": "doc", + "id": "operations/index" + } +} diff --git a/docs/src/operations/best-practices/_category_.json b/docs/src/operations/best-practices/_category_.json new file mode 100644 index 0000000000..caf50117dc --- /dev/null +++ b/docs/src/operations/best-practices/_category_.json @@ -0,0 +1,7 @@ +{ + "position": 7, + "label": "Best Practices", + "collapsible": true, + "collapsed": true, + "link": null +} diff --git a/docs/src/operations/best-practices/general.md b/docs/src/operations/best-practices/general.md new file mode 100644 index 0000000000..3bd0f906f7 --- /dev/null +++ b/docs/src/operations/best-practices/general.md @@ -0,0 +1,236 @@ +--- +title: Validator Operations Best Practices +sidebar_label: General Operations +--- + +After you have successfully setup and started a +[validator on testnet](../setup-a-validator.md) (or another cluster +of your choice), you will want to become familiar with how to operate your +validator on a day-to-day basis. During daily operations, you will be +[monitoring your server](./monitoring.md), updating software regularly (both the +Solana validator software and operating system packages), and managing your vote +account and identity account. + +All of these skills are critical to practice. Maximizing your validator uptime +is an important part of being a good operator. + +## Educational Workshops + +The Solana validator community holds regular educational workshops. You can +watch past workshops through the +[Solana validator educational workshops playlist](https://www.youtube.com/watch?v=86zySQ5vGW8&list=PLilwLeBwGuK6jKrmn7KOkxRxS9tvbRa5p). + +## Help with the validator command line + +From within the Solana CLI, you can execute the `solana-validator` command with +the `--help` flag to get a better understanding of the flags and sub commands +available. + +``` +solana-validator --help +``` + +## Restarting your validator + +There are many operational reasons you may want to restart your validator. As a +best practice, you should avoid a restart during a leader slot. A +[leader slot](https://solana.com/docs/terminology#leader-schedule) is the time +when your validator is expected to produce blocks. For the health of the cluster +and also for your validator's ability to earn transaction fee rewards, you do +not want your validator to be offline during an opportunity to produce blocks. + +To see the full leader schedule for an epoch, use the following command: + +``` +solana leader-schedule +``` + +Based on the current slot and the leader schedule, you can calculate open time +windows where your validator is not expected to produce blocks. + +Assuming you are ready to restart, you may use the `solana-validator exit` +command. The command exits your validator process when an appropriate idle time +window is reached. Assuming that you have systemd implemented for your validator +process, the validator should restart automatically after the exit. See the +below help command for details: + +``` +solana-validator exit --help +``` + +## Upgrading + +There are many ways to upgrade the +[Solana CLI software](../../cli/install.md). As an operator, you +will need to upgrade often, so it is important to get comfortable with this +process. + +> **Note** validator nodes do not need to be offline while the newest version is +> being downloaded or built from source. All methods below can be done before +> the validator process is restarted. + +### Building From Source + +It is a best practice to always build your Solana binaries from source. If you +build from source, you are certain that the code you are building has not been +tampered with before the binary was created. You may also be able to optimize +your `solana-validator` binary to your specific hardware. + +If you build from source on the validator machine (or a machine with the same +CPU), you can target your specific architecture using the `-march` flag. Refer +to the following doc for +[instructions on building from source](../../cli/install.md#build-from-source). + +### solana-install + +If you are not comfortable building from source, or you need to quickly install +a new version to test something out, you could instead try using the +`solana-install` command. + +Assuming you want to install Solana version `1.14.17`, you would execute the +following: + +``` +solana-install init 1.14.17 +``` + +This command downloads the executable for `1.14.17` and installs it into a +`.local` directory. You can also look at `solana-install --help` for more +options. + +> **Note** this command only works if you already have the solana cli installed. +> If you do not have the cli installed, refer to +> [install solana cli tools](../../cli/install.md) + +### Restart + +For all install methods, the validator process will need to be restarted before +the newly installed version is in use. Use `solana-validator exit` to restart +your validator process. + +### Verifying version + +The best way to verify that your validator process has changed to the desired +version is to grep the logs after a restart. The following grep command should +show you the version that your validator restarted with: + +``` +grep -B1 'Starting validator with' +``` + +## Snapshots + +Validators operators who have not experienced significant downtime (multiple +hours of downtime), should avoid downloading snapshots. It is important for the +health of the cluster as well as your validator history to maintain the local +ledger. Therefore, you should not download a new snapshot any time your +validator is offline or experiences an issue. Downloading a snapshot should only +be reserved for occasions when you do not have local state. Prolonged downtime +or the first install of a new validator are examples of times when you may not +have state locally. In other cases such as restarts for upgrades, a snapshot +download should be avoided. + +To avoid downloading a snapshot on restart, add the following flag to the +`solana-validator` command: + +``` +--no-snapshot-fetch +``` + +If you use this flag with the `solana-validator` command, make sure that you run +`solana catchup ` after your validator starts to make sure that the +validator is catching up in a reasonable time. After some time (potentially a +few hours), if it appears that your validator continues to fall behind, then you +may have to download a new snapshot. + +### Downloading Snapshots + +If you are starting a validator for the first time, or your validator has fallen +too far behind after a restart, then you may have to download a snapshot. + +To download a snapshot, you must **_NOT_** use the `--no-snapshot-fetch` flag. +Without the flag, your validator will automatically download a snapshot from +your known validators that you specified with the `--known-validator` flag. + +If one of the known validators is downloading slowly, you can try adding the +`--minimal-snapshot-download-speed` flag to your validator. This flag will +switch to another known validator if the initial download speed is below the +threshold that you set. + +### Manually Downloading Snapshots + +In the case that there are network troubles with one or more of your known +validators, then you may have to manually download the snapshot. To manually +download a snapshot from one of your known validators, first, find the IP +address of the validator in using the `solana gossip` command. In the example +below, `5D1fNXzvv5NjV1ysLjirC4WY92RNsVH18vjmcszZd8on` is the pubkey of one of my +known validators: + +``` +solana gossip | grep 5D1fNXzvv5NjV1ysLjirC4WY92RNsVH18vjmcszZd8on +``` + +The IP address of the validators is `139.178.68.207` and the open port on this +validator is `80`. You can see the IP address and port in the fifth column in +the gossip output: + +``` +139.178.68.207 | 5D1fNXzvv5NjV1ysLjirC4WY92RNsVH18vjmcszZd8on | 8001 | 8004 | 139.178.68.207:80 | 1.10.27 | 1425680972 +``` + +Now that the IP and port are known, you can download a full snapshot or an +incremental snapshot: + +``` +wget --trust-server-names http://139.178.68.207:80/snapshot.tar.bz2 +wget --trust-server-names http://139.178.68.207:80/incremental-snapshot.tar.bz2 +``` + +Now move those files into your snapshot directory. If you have not specified a +snapshot directory, then you should put the files in your ledger directory. + +Once you have a local snapshot, you can restart your validator with the +`--no-snapshot-fetch` flag. + +## Regularly Check Account Balances + +It is important that you do not accidentally run out of funds in your identity +account, as your node will stop voting. It is also important to note that this +account keypair is the most vulnerable of the three keypairs in a vote account +because the keypair for the identity account is stored on your validator when +running the `solana-validator` software. How much SOL you should store there is +up to you. As a best practice, make sure to check the account regularly and +refill or deduct from it as needed. To check the account balance do: + +``` +solana balance validator-keypair.json +``` + +> **Note** `solana-watchtower` can monitor for a minimum validator identity +> balance. See [monitoring best practices](./monitoring.md) for details. + +## Withdrawing From The Vote Account + +As a reminder, your withdrawer's keypair should **_NEVER_** be stored on your +server. It should be stored on a hardware wallet, paper wallet, or multisig +mitigates the risk of hacking and theft of funds. + +To withdraw your funds from your vote account, you will need to run +`solana withdraw-from-vote-account` on a trusted computer. For example, on a +trusted computer, you could withdraw all of the funds from your vote account +(excluding the rent exempt minimum). The below example assumes you have a +separate keypair to store your funds called `person-keypair.json` + +``` +solana withdraw-from-vote-account \ + vote-account-keypair.json \ + person-keypair.json ALL \ + --authorized-withdrawer authorized-withdrawer-keypair.json +``` + +To get more information on the command, use +`solana withdraw-from-vote-account --help`. + +For a more detailed explanation of the different keypairs and other related +operations refer to +[vote account management](../guides/vote-accounts.md). diff --git a/docs/src/validator/best-practices/monitoring.md b/docs/src/operations/best-practices/monitoring.md similarity index 100% rename from docs/src/validator/best-practices/monitoring.md rename to docs/src/operations/best-practices/monitoring.md diff --git a/docs/src/validator/best-practices/security.md b/docs/src/operations/best-practices/security.md similarity index 93% rename from docs/src/validator/best-practices/security.md rename to docs/src/operations/best-practices/security.md index 1e533dc860..d53491c115 100644 --- a/docs/src/validator/best-practices/security.md +++ b/docs/src/operations/best-practices/security.md @@ -26,7 +26,7 @@ To reiterate, the withdrawer keypair should never be stored on your validator at It may be easier to get started by running your application as root, but it is a bad practice. -If there is an exploit in your system, a hacker could have full access if your Solana application is running as the `root` user. Instead, see the [setup instructions](../get-started/setup-a-validator.md#sol-user) for creating a user called `sol` and running the application as the `sol` user. +If there is an exploit in your system, a hacker could have full access if your Solana application is running as the `root` user. Instead, see the [setup instructions](../setup-a-validator.md#sol-user) for creating a user called `sol` and running the application as the `sol` user. ## Close Ports That Are Not In Use diff --git a/docs/src/operations/guides/_category_.json b/docs/src/operations/guides/_category_.json new file mode 100644 index 0000000000..133867d408 --- /dev/null +++ b/docs/src/operations/guides/_category_.json @@ -0,0 +1,7 @@ +{ + "position": 8, + "label": "Validator Guides", + "collapsible": true, + "collapsed": true, + "link": null +} diff --git a/docs/src/running-validator/restart-cluster.md b/docs/src/operations/guides/restart-cluster.md similarity index 100% rename from docs/src/running-validator/restart-cluster.md rename to docs/src/operations/guides/restart-cluster.md diff --git a/docs/src/running-validator/validator-failover.md b/docs/src/operations/guides/validator-failover.md similarity index 100% rename from docs/src/running-validator/validator-failover.md rename to docs/src/operations/guides/validator-failover.md diff --git a/docs/src/running-validator/validator-info.md b/docs/src/operations/guides/validator-info.md similarity index 100% rename from docs/src/running-validator/validator-info.md rename to docs/src/operations/guides/validator-info.md diff --git a/docs/src/running-validator/validator-monitor.md b/docs/src/operations/guides/validator-monitor.md similarity index 100% rename from docs/src/running-validator/validator-monitor.md rename to docs/src/operations/guides/validator-monitor.md diff --git a/docs/src/running-validator/validator-stake.md b/docs/src/operations/guides/validator-stake.md similarity index 66% rename from docs/src/running-validator/validator-stake.md rename to docs/src/operations/guides/validator-stake.md index 71c9cd2130..a8d4bb9582 100644 --- a/docs/src/running-validator/validator-stake.md +++ b/docs/src/operations/guides/validator-stake.md @@ -46,7 +46,8 @@ and then delegating that stake to your validator: solana delegate-stake ~/validator-stake-keypair.json ~/vote-account-keypair.json ``` -> Don’t delegate your remaining SOL, as your validator will use those tokens to vote. +> Don’t delegate your remaining SOL, as your validator will use those tokens to +> vote. Stakes can be re-delegated to another node at any time with the same command, but only one re-delegation is permitted per epoch: @@ -57,23 +58,30 @@ solana delegate-stake ~/validator-stake-keypair.json ~/some-other-vote-account-k ## Validator Stake Warm-up -To combat various attacks on consensus, new stake delegations are subject to -a [warm-up](/staking/stake-accounts#delegation-warmup-and-cooldown) -period. +To combat various attacks on consensus, new stake delegations are subject to a +[warm-up](https://solana.com/docs/economics/staking/stake-accounts#delegation-warmup-and-cooldown) period. Monitor a validator's stake during warmup by: -- View your vote account:`solana vote-account ~/vote-account-keypair.json` This displays the current state of all the votes the validator has submitted to the network. -- View your stake account, the delegation preference and details of your stake:`solana stake-account ~/validator-stake-keypair.json` -- `solana validators` displays the current active stake of all validators, including yours -- `solana stake-history` shows the history of stake warming up and cooling down over recent epochs -- Look for log messages on your validator indicating your next leader slot: `[2019-09-27T20:16:00.319721164Z INFO solana_core::replay_stage] voted and reset PoH at tick height ####. My next leader slot is ####` -- Once your stake is warmed up, you will see a stake balance listed for your validator by running `solana validators` +- View your vote account:`solana vote-account ~/vote-account-keypair.json` This + displays the current state of all the votes the validator has submitted to the + network. +- View your stake account, the delegation preference and details of your + stake:`solana stake-account ~/validator-stake-keypair.json` +- `solana validators` displays the current active stake of all validators, + including yours +- `solana stake-history` shows the history of stake warming up and cooling down + over recent epochs +- Look for log messages on your validator indicating your next leader slot: + `[2019-09-27T20:16:00.319721164Z INFO solana_core::replay_stage] voted and reset PoH at tick height ####. My next leader slot is ####` +- Once your stake is warmed up, you will see a stake balance listed for your + validator by running `solana validators` ## Validator Rewards Once your stake is warmed up, and assuming the node is voting, you will now be -generating validator rewards. Rewards are paid automatically on epoch boundaries. +generating validator rewards. Rewards are paid automatically on epoch +boundaries. The rewards lamports earned are split between your stake account and the vote account according to the commission rate set in the vote account. Rewards can @@ -88,17 +96,24 @@ account. This is a normal transaction so the standard transaction fee will apply. The transaction fee range is defined by the genesis block. The actual fee will fluctuate based on transaction load. You can determine the current fee via the -[RPC API “getRecentBlockhash”](../api/http#getrecentblockhash) -before submitting a transaction. +[RPC API “getRecentBlockhash”](https://solana.com/docs/rpc/http/getrecentblockhash) before submitting +a transaction. -Learn more about [transaction fees here](../implemented-proposals/transaction-fees.md). +Learn more about +[transaction fees here](../../implemented-proposals/transaction-fees.md). ## Monitor Your Staked Validator -Confirm your validator becomes a [leader](../terminology.md#leader) +Confirm your validator becomes a +[leader](https://solana.com/docs/terminology#leader) -- After your validator is caught up, use the `solana balance` command to monitor the earnings as your validator is selected as leader and collects transaction fees -- Solana nodes offer a number of useful JSON-RPC methods to return information about the network and your validator's participation. Make a request by using curl \(or another http client of your choosing\), specifying the desired method in JSON-RPC-formatted data. For example: +- After your validator is caught up, use the `solana balance` command to monitor + the earnings as your validator is selected as leader and collects transaction + fees +- Solana nodes offer a number of useful JSON-RPC methods to return information + about the network and your validator's participation. Make a request by using + curl \(or another http client of your choosing\), specifying the desired + method in JSON-RPC-formatted data. For example: ```bash // Request @@ -110,9 +125,21 @@ Confirm your validator becomes a [leader](../terminology.md#leader) Helpful JSON-RPC methods: -- `getEpochInfo`[An epoch](../terminology.md#epoch) is the time, i.e. number of [slots](../terminology.md#slot), for which a [leader schedule](../terminology.md#leader-schedule) is valid. This will tell you what the current epoch is and how far into it the cluster is. -- `getVoteAccounts` This will tell you how much active stake your validator currently has. A % of the validator's stake is activated on an epoch boundary. You can learn more about staking on Solana [here](../cluster/stake-delegation-and-rewards.md). -- `getLeaderSchedule` At any given moment, the network expects only one validator to produce ledger entries. The [validator currently selected to produce ledger entries](../cluster/leader-rotation.md#leader-rotation) is called the “leader”. This will return the complete leader schedule \(on a slot-by-slot basis\) for currently activated stake, the identity pubkey will show up 1 or more times here. +- `getEpochInfo`[An epoch](https://solana.com/docs/terminology#epoch) is the + time, i.e. number of [slots](https://solana.com/docs/terminology#slot), for + which a [leader schedule](https://solana.com/docs/terminology#leader-schedule) + is valid. This will tell you what the current epoch is and how far into it the + cluster is. +- `getVoteAccounts` This will tell you how much active stake your validator + currently has. A % of the validator's stake is activated on an epoch boundary. + You can learn more about staking on Solana + [here](../../consensus/stake-delegation-and-rewards.md). +- `getLeaderSchedule` At any given moment, the network expects only one + validator to produce ledger entries. The + [validator currently selected to produce ledger entries](../../consensus/leader-rotation.md#leader-rotation) + is called the “leader”. This will return the complete leader schedule \(on a + slot-by-slot basis\) for currently activated stake, the identity pubkey will + show up 1 or more times here. ## Deactivating Stake @@ -124,8 +151,8 @@ solana deactivate-stake ~/validator-stake-keypair.json ``` Stake is not deactivated immediately and instead cools down in a similar fashion -as stake warm up. Your validator should remain attached to the cluster while -the stake is cooling down. While cooling down, your stake will continue to earn +as stake warm up. Your validator should remain attached to the cluster while the +stake is cooling down. While cooling down, your stake will continue to earn rewards. Only after stake cooldown is it safe to turn off your validator or withdraw it from the network. Cooldown may take several epochs to complete, depending on active stake and the size of your stake. diff --git a/docs/src/running-validator/validator-start.md b/docs/src/operations/guides/validator-start.md similarity index 77% rename from docs/src/running-validator/validator-start.md rename to docs/src/operations/guides/validator-start.md index ccd012aa79..69cef1315c 100644 --- a/docs/src/running-validator/validator-start.md +++ b/docs/src/operations/guides/validator-start.md @@ -12,7 +12,7 @@ solana config set --url http://api.devnet.solana.com ``` While this section demonstrates how to connect to the Devnet cluster, the steps -are similar for the other [Solana Clusters](../clusters.md). +are similar for the other [Solana Clusters](../../clusters/available.md). ## Confirm The Cluster Is Reachable @@ -97,7 +97,7 @@ EOF" #### System Clock -Large system clock drift can prevent a node from properly participating in Solana's [gossip protocol](../validator/gossip.md). Ensure that your system clock is accurate. To check the current system clock, use: +Large system clock drift can prevent a node from properly participating in Solana's [gossip protocol](../../validator/gossip.md). Ensure that your system clock is accurate. To check the current system clock, use: ```bash timedatectl @@ -138,7 +138,7 @@ solana-keygen pubkey ASK and then entering your seed phrase. -See [Paper Wallet Usage](../wallet-guide/paper-wallet.md) for more info. +See [Paper Wallet Usage](../../cli/wallets/paper.md) for more info. --- @@ -215,7 +215,7 @@ Or to see in finer detail: solana balance --lamports ``` -Read more about the [difference between SOL and lamports here](../introduction.md#what-are-sols). +Read more about the [difference between SOL and lamports here](https://solana.com/docs/intro#what-are-sols). ## Create Authorized Withdrawer Account @@ -253,13 +253,7 @@ solana create-vote-account ~/vote-account-keypair.json ~/validator-keypair.json Remember to move your authorized withdrawer keypair into a very secure location after running the above command. -Read more about [creating and managing a vote account](vote-accounts.md). - -## Stake your validator - -Until your validator is staked, it will be unable to vote, propose leader blocks, or collect rewards. - -Follow the instructions to [stake your validator](validator-stake.md) +Read more about [creating and managing a vote account](./vote-accounts.md). ## Known validators @@ -296,7 +290,7 @@ The ledger will be placed in the `ledger/` directory by default, use the `--ledger` argument to specify a different location. > Note: You can use a -> [paper wallet seed phrase](../wallet-guide/paper-wallet.md) +> [paper wallet seed phrase](../../cli/wallets/paper.md) > for your `--identity` and/or > `--authorized-voter` keypairs. To use these, pass the respective argument as > `solana-validator --identity ASK ... --authorized-voter ASK ...` @@ -321,7 +315,7 @@ the validator to ports 11000-11020. ### Limiting ledger size to conserve disk space The `--limit-ledger-size` parameter allows you to specify how many ledger -[shreds](../terminology.md#shred) your node retains on disk. If you do not +[shreds](https://solana.com/docs/terminology#shred) your node retains on disk. If you do not include this parameter, the validator will keep all received ledger data until it runs out of disk space. Otherwise, the validator will continually purge the oldest data once to stay under the specified `--limit-ledger-size` @@ -436,3 +430,52 @@ which starts the solana validator process uses "exec" to do so (example: "exec solana-validator ..."); otherwise, when logrotate sends its signal to the validator, the enclosing script will die and take the validator process with it. + +### Using a ramdisk with spill-over into swap for the accounts database to reduce SSD wear + +If your machine has plenty of RAM, a tmpfs ramdisk +([tmpfs](https://man7.org/linux/man-pages/man5/tmpfs.5.html)) may be used to hold +the accounts database + +When using tmpfs it's essential to also configure swap on your machine as well to +avoid running out of tmpfs space periodically. + +A 300GB tmpfs partition is recommended, with an accompanying 250GB swap +partition. + +Example configuration: + +1. `sudo mkdir /mnt/solana-accounts` +2. Add a 300GB tmpfs partition by adding a new line containing `tmpfs /mnt/solana-accounts tmpfs rw,size=300G,user=sol 0 0` to `/etc/fstab` + (assuming your validator is running under the user "sol"). **CAREFUL: If you + incorrectly edit /etc/fstab your machine may no longer boot** +3. Create at least 250GB of swap space + +- Choose a device to use in place of `SWAPDEV` for the remainder of these instructions. + Ideally select a free disk partition of 250GB or greater on a fast disk. If one is not + available, create a swap file with `sudo dd if=/dev/zero of=/swapfile bs=1MiB count=250KiB`, + set its permissions with `sudo chmod 0600 /swapfile` and use `/swapfile` as `SWAPDEV` for + the remainder of these instructions +- Format the device for usage as swap with `sudo mkswap SWAPDEV` + +4. Add the swap file to `/etc/fstab` with a new line containing `SWAPDEV swap swap defaults 0 0` +5. Enable swap with `sudo swapon -a` and mount the tmpfs with `sudo mount /mnt/solana-accounts/` +6. Confirm swap is active with `free -g` and the tmpfs is mounted with `mount` + +Now add the `--accounts /mnt/solana-accounts` argument to your `solana-validator` +command-line arguments and restart the validator. + +### Account indexing + +As the number of populated accounts on the cluster grows, account-data RPC +requests that scan the entire account set -- like +[`getProgramAccounts`](https://solana.com/docs/rpc/http/getprogramaccounts) and +[SPL-token-specific requests](https://solana.com/docs/rpc/http/gettokenaccountsbydelegate) -- +may perform poorly. If your validator needs to support any of these requests, +you can use the `--account-index` parameter to activate one or more in-memory +account indexes that significantly improve RPC performance by indexing accounts +by the key field. Currently supports the following parameter values: + +- `program-id`: each account indexed by its owning program; used by [getProgramAccounts](https://solana.com/docs/rpc/http/getprogramaccounts) +- `spl-token-mint`: each SPL token account indexed by its token Mint; used by [getTokenAccountsByDelegate](https://solana.com/docs/rpc/http/gettokenaccountsbydelegate), and [getTokenLargestAccounts](https://solana.com/docs/rpc/http/gettokenlargestaccounts) +- `spl-token-owner`: each SPL token account indexed by the token-owner address; used by [getTokenAccountsByOwner](https://solana.com/docs/rpc/http/gettokenaccountsbyowner), and [getProgramAccounts](https://solana.com/docs/rpc/http/getprogramaccounts) requests that include an spl-token-owner filter. diff --git a/docs/src/running-validator/validator-troubleshoot.md b/docs/src/operations/guides/validator-troubleshoot.md similarity index 95% rename from docs/src/running-validator/validator-troubleshoot.md rename to docs/src/operations/guides/validator-troubleshoot.md index a9defd8006..abf8d8f442 100644 --- a/docs/src/running-validator/validator-troubleshoot.md +++ b/docs/src/operations/guides/validator-troubleshoot.md @@ -2,7 +2,7 @@ title: Troubleshooting --- -There is a **\#validator-support** Discord channel available to reach other +There is a `#validator-support` Discord channel available to reach other testnet participants, [https://solana.com/discord](https://solana.com/discord) ## Useful Links & Discussion diff --git a/docs/src/running-validator/vote-accounts.md b/docs/src/operations/guides/vote-accounts.md similarity index 54% rename from docs/src/running-validator/vote-accounts.md rename to docs/src/operations/guides/vote-accounts.md index 6bb021588d..2c41165283 100644 --- a/docs/src/running-validator/vote-accounts.md +++ b/docs/src/operations/guides/vote-accounts.md @@ -8,8 +8,8 @@ account is needed if you plan to run a validator node on Solana. ## Create a Vote Account A vote account can be created with the -[create-vote-account](../cli/usage.md#solana-create-vote-account) command. -The vote account can be configured when first created or after the validator is +[create-vote-account](../../cli/usage.md#solana-create-vote-account) command. The +vote account can be configured when first created or after the validator is running. All aspects of the vote account can be changed except for the [vote account address](#vote-account-address), which is fixed for the lifetime of the account. @@ -17,114 +17,117 @@ of the account. ### Configure an Existing Vote Account - To change the [validator identity](#validator-identity), use - [vote-update-validator](../cli/usage.md#solana-vote-update-validator). + [vote-update-validator](../../cli/usage.md#solana-vote-update-validator). - To change the [vote authority](#vote-authority), use - [vote-authorize-voter-checked](../cli/usage.md#solana-vote-authorize-voter-checked). + [vote-authorize-voter-checked](../../cli/usage.md#solana-vote-authorize-voter-checked). - To change the [authorized withdrawer](#authorized-withdrawer), use - [vote-authorize-withdrawer-checked](../cli/usage.md#solana-vote-authorize-withdrawer-checked). + [vote-authorize-withdrawer-checked](../../cli/usage.md#solana-vote-authorize-withdrawer-checked). - To change the [commission](#commission), use - [vote-update-commission](../cli/usage.md#solana-vote-update-commission). + [vote-update-commission](../../cli/usage.md#solana-vote-update-commission). ## Vote Account Structure ### Vote Account Address A vote account is created at an address that is either the public key of a -keypair file, or at a derived address based on a keypair file's public key and -a seed string. +keypair file, or at a derived address based on a keypair file's public key and a +seed string. -The address of a vote account is never needed to sign any transactions, -but is just used to look up the account information. +The address of a vote account is never needed to sign any transactions, but is +just used to look up the account information. -When someone wants to [delegate tokens in a stake account](../staking.md), +When someone wants to +[delegate tokens in a stake account](https://solana.com/docs/economics/staking), the delegation command is pointed at the vote account address of the validator to whom the token-holder wants to delegate. ### Validator Identity The _validator identity_ is a system account that is used to pay for all the -vote transaction fees submitted to the vote account. -Because the validator is expected to vote on most valid blocks it receives, -the validator identity account is frequently -(potentially multiple times per second) signing transactions and -paying fees. For this reason the validator identity keypair must be -stored as a "hot wallet" in a keypair file on the same system the validator -process is running. +vote transaction fees submitted to the vote account. Because the validator is +expected to vote on most valid blocks it receives, the validator identity +account is frequently (potentially multiple times per second) signing +transactions and paying fees. For this reason the validator identity keypair +must be stored as a "hot wallet" in a keypair file on the same system the +validator process is running. Because a hot wallet is generally less secure than an offline or "cold" wallet, the validator operator may choose to store only enough SOL on the identity account to cover voting fees for a limited amount of time, such as a few weeks -or months. The validator identity account could be periodically topped off -from a more secure wallet. +or months. The validator identity account could be periodically topped off from +a more secure wallet. -This practice can reduce the risk of loss of funds if the validator node's -disk or file system becomes compromised or corrupted. +This practice can reduce the risk of loss of funds if the validator node's disk +or file system becomes compromised or corrupted. -The validator identity is required to be provided when a vote account is created. -The validator identity can also be changed after an account is created by using -the [vote-update-validator](../cli/usage.md#solana-vote-update-validator) command. +The validator identity is required to be provided when a vote account is +created. The validator identity can also be changed after an account is created +by using the +[vote-update-validator](../../cli/usage.md#solana-vote-update-validator) command. ### Vote Authority The _vote authority_ keypair is used to sign each vote transaction the validator node wants to submit to the cluster. This doesn't necessarily have to be unique -from the validator identity, as you will see later in this document. Because -the vote authority, like the validator identity, is signing transactions -frequently, this also must be a hot keypair on the same file system as the -validator process. +from the validator identity, as you will see later in this document. Because the +vote authority, like the validator identity, is signing transactions frequently, +this also must be a hot keypair on the same file system as the validator +process. -The vote authority can be set to the same address as the validator identity. -If the validator identity is also the vote authority, only one -signature per vote transaction is needed in order to both sign the vote and pay -the transaction fee. Because transaction fees on Solana are assessed -per-signature, having one signer instead of two will result in half the transaction -fee paid compared to setting the vote authority and validator identity to two -different accounts. +The vote authority can be set to the same address as the validator identity. If +the validator identity is also the vote authority, only one signature per vote +transaction is needed in order to both sign the vote and pay the transaction +fee. Because transaction fees on Solana are assessed per-signature, having one +signer instead of two will result in half the transaction fee paid compared to +setting the vote authority and validator identity to two different accounts. The vote authority can be set when the vote account is created. If it is not -provided, the default behavior is to assign it the same as the validator identity. -The vote authority can be changed later with the -[vote-authorize-voter-checked](../cli/usage.md#solana-vote-authorize-voter-checked) command. +provided, the default behavior is to assign it the same as the validator +identity. The vote authority can be changed later with the +[vote-authorize-voter-checked](../../cli/usage.md#solana-vote-authorize-voter-checked) +command. The vote authority can be changed at most once per epoch. If the authority is -changed with [vote-authorize-voter-checked](../cli/usage.md#solana-vote-authorize-voter-checked), -this will not take effect until the beginning of the next epoch. -To support a smooth transition of the vote signing, -`solana-validator` allows the `--authorized-voter` argument to be specified -multiple times. This allows the validator process to keep voting successfully -when the network reaches an epoch boundary at which the validator's vote -authority account changes. +changed with +[vote-authorize-voter-checked](../../cli/usage.md#solana-vote-authorize-voter-checked), +this will not take effect until the beginning of the next epoch. To support a +smooth transition of the vote signing, `solana-validator` allows the +`--authorized-voter` argument to be specified multiple times. This allows the +validator process to keep voting successfully when the network reaches an epoch +boundary at which the validator's vote authority account changes. ### Authorized Withdrawer -The _authorized withdrawer_ keypair is used to withdraw funds from a vote account -using the [withdraw-from-vote-account](../cli/usage.md#solana-withdraw-from-vote-account) +The _authorized withdrawer_ keypair is used to withdraw funds from a vote +account using the +[withdraw-from-vote-account](../../cli/usage.md#solana-withdraw-from-vote-account) command. Any network rewards a validator earns are deposited into the vote -account and are only retrievable by signing with the authorized withdrawer keypair. +account and are only retrievable by signing with the authorized withdrawer +keypair. -The authorized withdrawer is also required to sign any transaction to change -a vote account's [commission](#commission), and to change the validator -identity on a vote account. +The authorized withdrawer is also required to sign any transaction to change a +vote account's [commission](#commission), and to change the validator identity +on a vote account. Because theft of an authorized withdrawer keypair can give complete control over the operation of a validator to an attacker, it is advised to keep the withdraw -authority keypair in an offline/cold wallet in a secure location. The withdraw +authority keypair in an offline/cold wallet in a secure location. The withdraw authority keypair is not needed during operation of a validator and should not stored on the validator itself. -The authorized withdrawer must be set when the vote account is created. It must +The authorized withdrawer must be set when the vote account is created. It must not be set to a keypair that is the same as either the validator identity keypair or the vote authority keypair. The authorized withdrawer can be changed later with the -[vote-authorize-withdrawer-checked](../cli/usage.md#solana-vote-authorize-withdrawer-checked) +[vote-authorize-withdrawer-checked](../../cli/usage.md#solana-vote-authorize-withdrawer-checked) command. ### Commission _Commission_ is the percent of network rewards earned by a validator that are -deposited into the validator's vote account. The remainder of the rewards -are distributed to all of the stake accounts delegated to that vote account, +deposited into the validator's vote account. The remainder of the rewards are +distributed to all of the stake accounts delegated to that vote account, proportional to the active stake weight of each stake account. For example, if a vote account has a commission of 10%, for all rewards earned @@ -134,21 +137,22 @@ will be deposited into delegated stake accounts as immediately active stake. A validator may choose to set a low commission to try to attract more stake delegations as a lower commission results in a larger percentage of rewards -passed along to the delegator. As there are costs associated with setting up -and operating a validator node, a validator would ideally set a high enough +passed along to the delegator. As there are costs associated with setting up and +operating a validator node, a validator would ideally set a high enough commission to at least cover their expenses. Commission can be set upon vote account creation with the `--commission` option. -If it is not provided, it will default to 100%, which will result in all -rewards deposited in the vote account, and none passed on to any delegated -stake accounts. +If it is not provided, it will default to 100%, which will result in all rewards +deposited in the vote account, and none passed on to any delegated stake +accounts. Commission can also be changed later with the -[vote-update-commission](../cli/usage.md#solana-vote-update-commission) command. +[vote-update-commission](../../cli/usage.md#solana-vote-update-commission) command. -When setting the commission, only integer values in the set [0-100] are accepted. -The integer represents the number of percentage points for the commission, so -creating an account with `--commission 10` will set a 10% commission. +When setting the commission, only integer values in the set [0-100] are +accepted. The integer represents the number of percentage points for the +commission, so creating an account with `--commission 10` will set a 10% +commission. Note that validators can only update their commission during the first half of any epoch. This prevents validators from stealing delegator rewards by setting a @@ -167,17 +171,21 @@ without any impact to staking rewards. ### Vote Account Validator Identity -You will need access to the _authorized withdrawer_ keypair for the vote account to -change the validator identity. The following steps assume that +You will need access to the _authorized withdrawer_ keypair for the vote account +to change the validator identity. The following steps assume that `~/authorized_withdrawer.json` is that keypair. -1. Create the new validator identity keypair, `solana-keygen new -o ~/new-validator-keypair.json`. -2. Ensure that the new identity account has been funded, `solana transfer ~/new-validator-keypair.json 500`. -3. Run `solana vote-update-validator ~/vote-account-keypair.json ~/new-validator-keypair.json ~/authorized_withdrawer.json` +1. Create the new validator identity keypair, + `solana-keygen new -o ~/new-validator-keypair.json`. +2. Ensure that the new identity account has been funded, + `solana transfer ~/new-validator-keypair.json 500`. +3. Run + `solana vote-update-validator ~/vote-account-keypair.json ~/new-validator-keypair.json ~/authorized_withdrawer.json` to modify the validator identity in your vote account -4. Restart your validator with the new identity keypair for the `--identity` argument +4. Restart your validator with the new identity keypair for the `--identity` + argument -**Additional steps are required if your validator has stake.** The leader +**Additional steps are required if your validator has stake.** The leader schedule is computed two epochs in advance. Therefore if your old validator identity was in the leader schedule, it will remain in the leader schedule for up to two epochs after the validator identity change. If extra steps are not @@ -185,12 +193,16 @@ taken your validator will produce no blocks until your new validator identity is added to the leader schedule. After your validator is restarted with the new identity keypair, per step 4, -start a second non-voting validator on a different machine with the old identity keypair -without providing the `--vote-account` argument, as well as with the `--no-wait-for-vote-to-start-leader` argument. +start a second non-voting validator on a different machine with the old identity +keypair without providing the `--vote-account` argument, as well as with the +`--no-wait-for-vote-to-start-leader` argument. -This temporary validator should be run for two full epochs. During this time it will: -* Produce blocks for the remaining slots that are assigned to your old validator identity -* Receive the transaction fees and rent rewards for your old validator identity +This temporary validator should be run for two full epochs. During this time it +will: + +- Produce blocks for the remaining slots that are assigned to your old validator + identity +- Receive the transaction fees and rent rewards for your old validator identity It is safe to stop this temporary validator when your old validator identity is no longer listed in the `solana leader-schedule` output. @@ -204,44 +216,64 @@ migration. 1. Run `solana epoch-info`. If there is not much time remaining time in the current epoch, consider waiting for the next epoch to allow your validator plenty of time to restart and catch up. -2. Create the new vote authority keypair, `solana-keygen new -o ~/new-vote-authority.json`. -3. Determine the current _vote authority_ keypair by running `solana vote-account ~/vote-account-keypair.json`. It may be validator's +2. Create the new vote authority keypair, + `solana-keygen new -o ~/new-vote-authority.json`. +3. Determine the current _vote authority_ keypair by running + `solana vote-account ~/vote-account-keypair.json`. It may be validator's identity account (the default) or some other keypair. The following steps assume that `~/validator-keypair.json` is that keypair. -4. Run `solana vote-authorize-voter-checked ~/vote-account-keypair.json ~/validator-keypair.json ~/new-vote-authority.json`. - The new vote authority is scheduled to become active starting at the next epoch. +4. Run + `solana vote-authorize-voter-checked ~/vote-account-keypair.json ~/validator-keypair.json ~/new-vote-authority.json`. + The new vote authority is scheduled to become active starting at the next + epoch. 5. `solana-validator` now needs to be restarted with the old and new vote authority keypairs, so that it can smoothly transition at the next epoch. Add - the two arguments on restart: `--authorized-voter ~/validator-keypair.json --authorized-voter ~/new-vote-authority.json` + the two arguments on restart: + `--authorized-voter ~/validator-keypair.json --authorized-voter ~/new-vote-authority.json` 6. After the cluster reaches the next epoch, remove the `--authorized-voter ~/validator-keypair.json` argument and restart `solana-validator`, as the old vote authority keypair is no longer required. ### Vote Account Authorized Withdrawer -No special handling or timing considerations are required. -Use the `solana vote-authorize-withdrawer-checked` command as needed. +No special handling or timing considerations are required. Use the +`solana vote-authorize-withdrawer-checked` command as needed. ### Consider Durable Nonces for a Trustless Transfer of the Authorized Voter or Withdrawer If the Authorized Voter or Withdrawer is to be transferred to another entity -then a two-stage signing process using a [Durable Nonce](../offline-signing/durable-nonce) is recommended. +then a two-stage signing process using a +[Durable Nonce](../../cli/examples/durable-nonce.md) is recommended. 1. Entity B creates a durable nonce using `solana create-nonce-account` -2. Entity B then runs a `solana vote-authorize-voter-checked` or `solana vote-authorize-withdrawer-checked` command, including: - - the `--sign-only` argument - - the `--nonce`, `--nonce-authority`, and `--blockhash` arguments to specify the nonce particulars - - the address of the Entity A's existing authority, and the keypair for Entity B's new authority -3. When the `solana vote-authorize-...-checked` command successfully executes, it will output transaction signatures that Entity B must share with Entity A -4. Entity A then runs a similar `solana vote-authorize-voter-checked` or `solana vote-authorize-withdrawer-checked` command with the following changes: - - the `--sign-only` argument is removed, and replaced with a `--signer` argument for each of the signatures provided by Entity B - - the address of Entity A's existing authority is replaced with the corresponding keypair, and the keypair for Entity B's new authority is replaced with the corresponding address +2. Entity B then runs a `solana vote-authorize-voter-checked` or + `solana vote-authorize-withdrawer-checked` command, including: -On success the authority is now changed without Entity A or B having to reveal keypairs to the other even though both entities signed the transaction. +- the `--sign-only` argument +- the `--nonce`, `--nonce-authority`, and `--blockhash` arguments to specify the + nonce particulars +- the address of the Entity A's existing authority, and the keypair for Entity + B's new authority + +3. When the `solana vote-authorize-...-checked` command successfully executes, + it will output transaction signatures that Entity B must share with Entity A +4. Entity A then runs a similar `solana vote-authorize-voter-checked` or + `solana vote-authorize-withdrawer-checked` command with the following + changes: + +- the `--sign-only` argument is removed, and replaced with a `--signer` argument + for each of the signatures provided by Entity B +- the address of Entity A's existing authority is replaced with the + corresponding keypair, and the keypair for Entity B's new authority is + replaced with the corresponding address + +On success the authority is now changed without Entity A or B having to reveal +keypairs to the other even though both entities signed the transaction. ## Close a Vote Account A vote account can be closed with the -[close-vote-account](../cli/usage.md#solana-close-vote-account) command. -Closing a vote account withdraws all remaining SOL funds to a supplied recipient address and renders it invalid as a vote account. -It is not possible to close a vote account with active stake. +[close-vote-account](../../cli/usage.md#solana-close-vote-account) command. Closing +a vote account withdraws all remaining SOL funds to a supplied recipient address +and renders it invalid as a vote account. It is not possible to close a vote +account with active stake. diff --git a/docs/src/operations/index.md b/docs/src/operations/index.md new file mode 100644 index 0000000000..51e29ac407 --- /dev/null +++ b/docs/src/operations/index.md @@ -0,0 +1,8 @@ +--- +title: Operating a Validator +sidebar_position: 0 +--- + +This section describes how to run a Solana validator node. + +There are several clusters available to connect to; see [Choosing a Cluster](../cli/examples/choose-a-cluster.md) for an overview of each. diff --git a/docs/src/validator/overview/validator-prerequisites.md b/docs/src/operations/prerequisites.md similarity index 68% rename from docs/src/validator/overview/validator-prerequisites.md rename to docs/src/operations/prerequisites.md index 2bf2af278a..c44c15fc20 100644 --- a/docs/src/validator/overview/validator-prerequisites.md +++ b/docs/src/operations/prerequisites.md @@ -1,6 +1,7 @@ --- title: Solana Validator Prerequisites -sidebar_label: Validator Prerequisites +sidebar_label: Prerequisites +sidebar_position: 2 --- Operating a Solana validator is an interesting and rewarding task. Generally speaking, it requires someone with a technical background but also involves community engagement and marketing. @@ -10,7 +11,7 @@ Operating a Solana validator is an interesting and rewarding task. Generally spe Here is a list of some of the requirements for being a good operator: - Performant computer hardware and a fast internet connection - - You can find a list of [hardware requirements here](../../running-validator/validator-reqs.md) + - You can find a list of [hardware requirements here](./requirements.md) - Solana helps facilitate data-center server rentals through the [Solana server program](https://solana.foundation/server-program) - Knowledge of the Linux terminal - Ubuntu system administration @@ -26,10 +27,10 @@ Here is a list of some of the requirements for being a good operator: - Marketing and communications to attract delegators - Customer support -Whether you decide to run a [validator](./what-is-a-validator.md) or an [RPC node](./what-is-an-rpc-node.md), you should consider all of these areas of expertise. A team of people is likely necessary for you to achieve your goals. +Whether you decide to run a [validator](../what-is-a-validator.md) or an [RPC node](../what-is-an-rpc-node.md), you should consider all of these areas of expertise. A team of people is likely necessary for you to achieve your goals. ## Can I use my computer at home? -While anyone can join the network, you should make sure that your home computer and network meets the specifications in the [hardware requirements](../../running-validator/validator-reqs.md) doc. Most home internet service providers do not provide consistent service that would allow your validator to perform well. If your home network or personal hardware is not performant enough to keep up with the Solana cluster, your validator will not be able to participate in consensus. +While anyone can join the network, you should make sure that your home computer and network meets the specifications in the [hardware requirements](./requirements.md) doc. Most home internet service providers do not provide consistent service that would allow your validator to perform well. If your home network or personal hardware is not performant enough to keep up with the Solana cluster, your validator will not be able to participate in consensus. In addition to performance considerations, you will want to make sure that your home computer is resistant to outages caused by loss of power, flooding, fire, theft, etc. If you are just getting started and learning about being an operator, a home setup may be sufficient, but you will want to consider all of these factors when you start operating your validator on the mainnet-beta cluster. \ No newline at end of file diff --git a/docs/src/running-validator/validator-reqs.md b/docs/src/operations/requirements.md similarity index 96% rename from docs/src/running-validator/validator-reqs.md rename to docs/src/operations/requirements.md index c3e9f937c9..8c9e8d62cb 100644 --- a/docs/src/running-validator/validator-reqs.md +++ b/docs/src/operations/requirements.md @@ -1,5 +1,7 @@ --- title: Validator Requirements +sidebar_label: Requirements +sidebar_position: 3 --- ## Minimum SOL requirements @@ -88,7 +90,7 @@ releases at [solanalabs/solana](https://hub.docker.com/r/solanalabs/solana). ## Software - We build and run on Ubuntu 20.04. -- See [Installing Solana](../cli/install-solana-cli-tools.md) for the current Solana software release. +- See [Installing Solana CLI](../cli/install.md) for the current Solana software release. Prebuilt binaries are available for Linux x86_64 on CPUs supporting AVX2 \(Ubuntu 20.04 recommended\). MacOS or WSL users may build from source. diff --git a/docs/src/validator/get-started/setup-a-validator.md b/docs/src/operations/setup-a-validator.md similarity index 90% rename from docs/src/validator/get-started/setup-a-validator.md rename to docs/src/operations/setup-a-validator.md index 8379b6f1d1..2a955e03a1 100644 --- a/docs/src/validator/get-started/setup-a-validator.md +++ b/docs/src/operations/setup-a-validator.md @@ -1,11 +1,14 @@ --- title: Setup a Solana Validator sidebar_label: Setup a Validator +sidebar_position: 5 --- This is a guide for getting your validator setup on the Solana testnet cluster for the first time. Testnet is a Solana cluster that is used for performance testing of the software before the software is used on mainnet. Since testnet is stress tested daily, it is a good cluster to practice validator operations. -Once you have a working validator on testnet, you will want to learn about [operational best practices](../best-practices/operations.md) in the next section. Although the guide is specific to testnet, it can be adapted to mainnet or devnet as well. Refer to the [clusters](../../clusters) section of the Solana docs to see example commands for each cluster. +Once you have a working validator on testnet, you will want to learn about [operational best practices](./best-practices/general.md) in the next section. Although the guide is specific to testnet, it can be adapted to mainnet or devnet as well. + +> Refer to the [Available Clusters](../clusters/available.md) section of the documentation to see example commands for each cluster. Now let's get started. @@ -19,9 +22,9 @@ To start this guide, you will be running commands on your trusted computer, not ## Install The Solana CLI Locally -To create your validator vote account, you need to install the [Solana command line interface](../../cli.md) on your local computer. +To create your validator vote account, you need to install the [Solana command line interface](../cli/index.md) on your local computer. -You can either use [Solana's Install Tool](../../cli/install-solana-cli-tools#use-solanas-install-tool) section from the Solana docs to install the CLI, or alternatively, you can also [build from source](../../cli/install-solana-cli-tools#build-from-source). +You can either use [Solana's Install Tool](../cli/install.md#use-solanas-install-tool) section from the within these docs to install the CLI, or alternatively, you can also [build from source](../cli/install.md#build-from-source). > Building from source is a great option for those that want a more secure and potentially more performant executable. @@ -53,9 +56,9 @@ You should see a line that says: `RPC URL: https://api.testnet.solana.com` ## Create Keys -On your local computer, create the 3 keypairs that you will need to run your validator ([docs for reference](../../running-validator/validator-start#generate-identity)): +On your local computer, create the 3 keypairs that you will need to run your validator ([docs for reference](./guides/validator-start.md#generate-identity)): -> **NOTE** Some operators choose to make vanity keypairs for their identity and vote account using the `grind` sub command ([docs for reference](../../running-validator/validator-start#vanity-keypair)). +> **NOTE** Some operators choose to make vanity keypairs for their identity and vote account using the `grind` sub command ([docs for reference](./guides/validator-start.md#vanity-keypair)). ``` solana-keygen new -o validator-keypair.json @@ -69,7 +72,7 @@ solana-keygen new -o vote-account-keypair.json solana-keygen new -o authorized-withdrawer-keypair.json ``` -> **IMPORTANT** the `authorized-withdrawer-keypair.json` should be considered very sensitive information. Many operators choose to use a multisig, hardware wallet, or paper wallet for the authorized withdrawer keypair. A keypair is created on disk in this example for simplicity. Additionally, the withdrawer keypair should always be stored safely. The authorized withdrawer keypair should **never** be stored on the remote machine that the validator software runs on. For more information, see [validator security best practices](../best-practices/security.md#do-not-store-your-withdrawer-key-on-your-validator) +> **IMPORTANT** the `authorized-withdrawer-keypair.json` should be considered very sensitive information. Many operators choose to use a multisig, hardware wallet, or paper wallet for the authorized withdrawer keypair. A keypair is created on disk in this example for simplicity. Additionally, the withdrawer keypair should always be stored safely. The authorized withdrawer keypair should **never** be stored on the remote machine that the validator software runs on. For more information, see [validator security best practices](./best-practices/security.md#do-not-store-your-withdrawer-key-on-your-validator) ## Create a Vote Account @@ -317,7 +320,7 @@ su - sol ## Install The Solana CLI on Remote Machine -Your remote machine will need the Solana cli installed to run the validator software. Refer again to [Solana's Install Tool](../../cli/install-solana-cli-tools#use-solanas-install-tool) or [build from source](../../cli/install-solana-cli-tools#build-from-source). It is best for operators to build from source rather than using the pre built binaries. +Your remote machine will need the Solana cli installed to run the validator software. Refer again to [Solana's Install Tool](../cli/install.md#use-solanas-install-tool) or [build from source](../cli/install.md#build-from-source). It is best for operators to build from source rather than using the pre built binaries. ## Create A Validator Startup Script @@ -358,7 +361,7 @@ exec solana-validator \ --limit-ledger-size ``` -Refer to `solana-validator --help` for more information on what each flag is doing in this script. Also refer to the section on [best practices for operating a validator](../best-practices/operations.md). +Refer to `solana-validator --help` for more information on what each flag is doing in this script. Also refer to the section on [best practices for operating a validator](./best-practices/general.md). ## Verifying Your Validator Is Working @@ -395,7 +398,7 @@ Assuming you do not see any error messages, exit out of the command. ### Gossip Protocol -Gossip is a protocol used in the Solana clusters to communicate between validator nodes. For more information on gossip, see [Gossip Service](../gossip.md). To verify that your validator is running properly, make sure that the validator has registered itself with the gossip network. +Gossip is a protocol used in the Solana clusters to communicate between validator nodes. For more information on gossip, see [Gossip Service](../validator/gossip.md). To verify that your validator is running properly, make sure that the validator has registered itself with the gossip network. In a new terminal window, connect to your server via ssh. Identify your validator's pubkey: @@ -447,7 +450,7 @@ Once you are happy that the validator can start up without errors, the next step ## Create a System Service -Follow these instructions for [running the validator as a system service](../../running-validator/validator-start#systemd-unit) +Follow these instructions for [running the validator as a system service](./guides/validator-start.md#systemd-unit) Make sure to implement log rotate as well. Once you have the system service configured, start your validator using the newly configured service: @@ -463,7 +466,7 @@ tail -f /home/sol/solana-validator*.log ## Monitoring -`solana-watchtower` is a command you can run on a separate machine to monitor your server. You can read more about handling [automatic restarts and monitoring](../best-practices/monitoring.md#solana-watchtower) using Solana Watchtower here in the docs. +`solana-watchtower` is a command you can run on a separate machine to monitor your server. You can read more about handling [automatic restarts and monitoring](./best-practices/monitoring.md#solana-watchtower) using Solana Watchtower here in the docs. ## Common issues diff --git a/docs/src/validator/get-started/setup-an-rpc-node.md b/docs/src/operations/setup-an-rpc-node.md similarity index 81% rename from docs/src/validator/get-started/setup-an-rpc-node.md rename to docs/src/operations/setup-an-rpc-node.md index 2c3f350310..e65e35542e 100644 --- a/docs/src/validator/get-started/setup-an-rpc-node.md +++ b/docs/src/operations/setup-an-rpc-node.md @@ -1,6 +1,7 @@ --- title: Setup a Solana RPC Node sidebar_label: Setup an RPC Node +sidebar_position: 6 --- Since a Solana RPC server runs the same process as a consensus validator, first follow the instructions on [how to setup a Solana validator](./setup-a-validator.md) to get started. Note, that you do not need to create a vote account if you are operating an RPC node. An RPC node typically does not vote. @@ -55,7 +56,7 @@ If you are interested in setting up your own bigtable instance, see these docs i ### Example Known Validators -The identities of the [known validators](../../running-validator/validator-start.md#known-validators) supplied in these example snippets (via the `--known-validator` flag) are: +The identities of the [known validators](./guides/validator-start.md#known-validators) supplied in these example snippets (via the `--known-validator` flag) are: - `5D1fNXzvv5NjV1ysLjirC4WY92RNsVH18vjmcszZd8on` - Solana Labs - `dDzy5SR3AXdYWVqbDEkVFdvSPCtS9ihF5kJkHCtXoFs` - MonkeDAO @@ -65,7 +66,7 @@ The identities of the [known validators](../../running-validator/validator-start ## Examples for other clusters -Additional examples of other Solana cluster specific validator commands can be found on the [Clusters](../../clusters.md) page. +Additional examples of other Solana cluster specific validator commands can be found on the [Clusters](../clusters/available.md) page. Keep in mind, you will still need to customize these commands to operate as an RPC node, as well other operator specific configuration settings. @@ -73,13 +74,13 @@ Keep in mind, you will still need to customize these commands to operate as an R As the number of populated accounts on the cluster grows, account-data RPC requests that scan the entire account set -- like -[`getProgramAccounts`](../../api/http#getprogramaccounts) and -[SPL-token-specific requests](../../api/http#gettokenaccountsbydelegate) -- +[`getProgramAccounts`](https://solana.com/docs/rpc/http/getprogramaccounts) and +[SPL-token-specific requests](https://solana.com/docs/rpc/http/gettokenaccountsbydelegate) -- may perform poorly. If your validator needs to support any of these requests, you can use the `--account-index` parameter to activate one or more in-memory account indexes that significantly improve RPC performance by indexing accounts by the key field. Currently supports the following parameter values: -- `program-id`: each account indexed by its owning program; used by [getProgramAccounts](../../api/http#getprogramaccounts) -- `spl-token-mint`: each SPL token account indexed by its token Mint; used by [getTokenAccountsByDelegate](../../api/http#gettokenaccountsbydelegate), and [getTokenLargestAccounts](../../api/http#gettokenlargestaccounts) -- `spl-token-owner`: each SPL token account indexed by the token-owner address; used by [getTokenAccountsByOwner](../../api/http#gettokenaccountsbyowner), and [getProgramAccounts](../../api/http#getprogramaccounts) requests that include an spl-token-owner filter. +- `program-id`: each account indexed by its owning program; used by [getProgramAccounts](https://solana.com/docs/rpc/http/getprogramaccounts) +- `spl-token-mint`: each SPL token account indexed by its token Mint; used by [getTokenAccountsByDelegate](https://solana.com/docs/rpc/http/gettokenaccountsbydelegate), and [getTokenLargestAccounts](https://solana.com/docs/rpc/http/gettokenlargestaccounts) +- `spl-token-owner`: each SPL token account indexed by the token-owner address; used by [getTokenAccountsByOwner](https://solana.com/docs/rpc/http/gettokenaccountsbyowner), and [getProgramAccounts](https://solana.com/docs/rpc/http/getprogramaccounts) requests that include an spl-token-owner filter. diff --git a/docs/src/validator/overview/validator-initiatives.md b/docs/src/operations/validator-initiatives.md similarity index 85% rename from docs/src/validator/overview/validator-initiatives.md rename to docs/src/operations/validator-initiatives.md index a410aba5e7..f0f1495159 100644 --- a/docs/src/validator/overview/validator-initiatives.md +++ b/docs/src/operations/validator-initiatives.md @@ -1,6 +1,7 @@ --- title: Solana Validator Initiatives sidebar_label: Validator Initiatives +sidebar_position: 4 --- There are a number of initiatives that may help operators get started or grow their delegation. All of these initiatives are completely optional. All Solana clusters are permissionless and an operator can join at any time. @@ -16,7 +17,7 @@ Delegation program participants who operate a performant testnet node, may also ## Solana Foundation Server Program -Separately from the delegation program, The Solana Foundation offers a server program that provides servers in various data-centers all over the world. If you would like to run a consensus validator or RPC node, you may use this program to rent bare metal servers in various data-centers. The servers meet or exceed the [Solana validator hardware specs](../../running-validator/validator-reqs#hardware-recommendations). No long-term lease commitments are required. To find out more, visit the [Solana server program page](https://solana.org/server-program). +Separately from the delegation program, The Solana Foundation offers a server program that provides servers in various data-centers all over the world. If you would like to run a consensus validator or RPC node, you may use this program to rent bare metal servers in various data-centers. The servers meet or exceed the [Solana validator hardware specs](./requirements.md#hardware-recommendations). No long-term lease commitments are required. To find out more, visit the [Solana server program page](https://solana.org/server-program). ## Stake Pools diff --git a/docs/src/operations/validator-or-rpc-node.md b/docs/src/operations/validator-or-rpc-node.md new file mode 100644 index 0000000000..c07c5201f1 --- /dev/null +++ b/docs/src/operations/validator-or-rpc-node.md @@ -0,0 +1,91 @@ +--- +title: Consensus Validator or RPC Node? +sidebar_label: Validator vs RPC Node +sidebar_position: 1 +--- + +Operators who run a [consensus validator](../what-is-a-validator.md) have much +different incentives than operators who run an +[RPC node](../what-is-an-rpc-node.md). You will have to decide which choice is +best for you based on your interests, technical background, and goals. + +## Consensus Validators + +As a validator your primary focus is maintaining the network and making sure +that your node is performing optimally so that you can fully participate in the +cluster consensus. You will want to attract a delegation of SOL to your +validator which will allow your validator the opportunity to produce more blocks +and earn rewards. + +Each staked validator earns inflation rewards from +[vote credits](https://solana.com/docs/terminology#vote-credit). Vote credits +are assigned to validators that vote on +[blocks](https://solana.com/docs/terminology#block) produced by the +[leader](https://solana.com/docs/terminology#leader). The vote credits are given +to all validators that successfully vote on blocks that are added to the +blockchain. Additionally, when the validator is the leader, it can earn +transaction fees and storage +[rent fees](https://solana.com/docs/core/accounts#rent) for each block that it +produces that is added to the blockchain. + +Since all votes in Solana happen on the blockchain, a validator incurs a +transaction cost for each vote that it makes. These transaction fees amount to +approximately 1.0 SOL per day. + +> It is important to make sure your validator always has enough SOL in its +> identity account to pay for these transactions! + +### Economics of running a consensus validator + +As an operator, it is important to understand how a consensus validator spends +and earns sol through the protocol. + +All validators who vote (consensus validators) must pay vote transaction fees +for blocks that they agree with. The cost of voting can be up to 1.1 SOL per +day. + +A voting validator can earn SOL through 2 methods: + +1. Inflationary rewards paid at the end of an epoch. See + [staking rewards](../implemented-proposals/staking-rewards.md) +2. Earning 50% of transaction fees for the blocks produced by the validator. See + [transaction fee basic economic design](https://solana.com/docs/intro/transaction_fees#basic-economic-design) + +The following links are community provided resources that discuss the economics +of running a validator: + +- Michael Hubbard wrote an + [article](https://laine-sa.medium.com/solana-staking-rewards-validator-economics-how-does-it-work-6718e4cccc4e) + that explains the economics of Solana in more depth for stakers and for + validators. +- Congent Crypto has written a + [blog post](https://medium.com/@Cogent_Crypto/how-to-become-a-validator-on-solana-9dc4288107b7) + that discusses economics and getting started. +- Cogent Crypto also provides a + [validator profit calculator](https://cogentcrypto.io/ValidatorProfitCalculator) + +## RPC Nodes + +While RPC operators **do NOT** receive rewards (because the node is not +participating in voting), there are different motivations for running an RPC +node. + +An RPC operator is providing a service to users who want to interact with the +Solana blockchain. Because your primary user is often technical, you will have +to be able to answer technical questions about performance of RPC calls. This +option may require more understanding of the +[core Solana architecture](../clusters/index.md). + +If you are operating an RPC node as a business, your job will also involve +scaling your system to meet the demands of the users. For example, some RPC +providers create dedicated servers for projects that require a high volume of +requests to the node. Someone with a background in development operations or +software engineering will be a very important part of your team. You will need a +strong understanding of the Solana architecture and the +[JSON RPC API](https://solana.com/docs/rpc/http). + +Alternatively, you may be a development team that would like to run their own +infrastructure. In this case, the RPC infrastructure could be a part of your +production stack. A development team could use the +[Geyser plugin](../validator/geyser.md), for example, to get +real time access to information about accounts or blocks in the cluster. diff --git a/docs/src/pages/CodeDocBlock.module.css b/docs/src/pages/CodeDocBlock.module.css deleted file mode 100644 index 7cffc5625b..0000000000 --- a/docs/src/pages/CodeDocBlock.module.css +++ /dev/null @@ -1,80 +0,0 @@ -/* stylelint-disable docusaurus/copyright-header */ - -.DocBlock { - border-top: 1px solid #414141; - padding-top: 3rem; - /* display: flex; */ - /* justify-content: space-between; */ - margin-top: 5rem; - /* width: 100%; */ - /* align-items: center; */ -} - -.DocSideBySide { - margin-top: 2rem; -} - -.CodeParams { - display: block; - width: 100%; -} - -.CodeSnippets { - display: block; - width: 100%; -} - -@media screen and (min-width: 768px) { - .DocSideBySide { - display: flex; - width: 100%; - } - .CodeParams { - margin-right: 3rem; - width: 50%; - } - .CodeSnippets { - width: 50%; - } -} - -.Parameter { - padding: 1em 0em; - margin-bottom: 1em; - border-top: 1px solid #414141; - /* // border-bottom: 1px solid #414141; */ -} - -.ParameterName { - font-weight: 700; -} - -.ParameterHeader { - font-family: mono; - padding: 0.1em 0em; -} - -.Field { - /* // padding: 1em 0em; */ - margin: 1em 0em 1em 1em; - /* // border-top: 1px solid #414141; */ - /* // border-bottom: 1px solid #414141; */ -} -.Field section { - padding: 0em 1em; -} - -.FlagItem { - margin: 0 0.5rem; - color: #767676; - font-weight: 600; -} - -.Heading { - font-size: 1.24rem; - font-weight: 700; -} -.SubHeading { - /* font-size: 1.24rem; */ - font-weight: 600; -} diff --git a/docs/src/pages/api.js b/docs/src/pages/api.js deleted file mode 100644 index 6252d21df5..0000000000 --- a/docs/src/pages/api.js +++ /dev/null @@ -1,82 +0,0 @@ -import React from "react"; -import Link from "@docusaurus/Link"; -import styles from "./styles.module.css"; -import Card from "../../components/Card"; -import CardLayout from "../../layouts/CardLayout"; - -function APIPage() { - return ( - -
    -
    -
    -

    JSON RPC API

    - -
    -

    - Interact with Solana nodes directly with the JSON RPC API via - the HTTP and Websocket methods. -

    - - - Explore the API - -
    -
    - -
    -

    Explore the JSON RPC Methods

    - -
    - - - - - -
    -
    -
    -
    -
    - ); -} - -export default APIPage; diff --git a/docs/src/pages/developers.js b/docs/src/pages/developers.js deleted file mode 100644 index 059622e365..0000000000 --- a/docs/src/pages/developers.js +++ /dev/null @@ -1,171 +0,0 @@ -import React from "react"; -import Link from "@docusaurus/Link"; -import styles from "./styles.module.css"; -import Card from "../../components/Card"; -import CardLayout from "../../layouts/CardLayout"; - -function Developers() { - return ( - -
    -
    -
    -

    Learn Solana Development

    - -
    -

    - Build and deploy your first on chain Solana program directly in - your browser. -

    - - - Get Started - -
    -
    - -
    -

    Learn core concepts

    - -
    - - - - - -
    -
    - -
    -

    Learn through coding

    - -
    - - - -
    -
    - -
    -

    Setup your local development

    - -
    - - - - {/* future card to replace the RPC API card */} - {/* */} - - -
    -
    -
    -
    -
    - ); -} - -export default Developers; diff --git a/docs/src/pages/getstarted.jsx b/docs/src/pages/getstarted.jsx deleted file mode 100644 index 57d2c591bc..0000000000 --- a/docs/src/pages/getstarted.jsx +++ /dev/null @@ -1,138 +0,0 @@ -import React from "react"; -import Link from "@docusaurus/Link"; -import styles from "./styles.module.css"; -import Card from "../../components/Card"; -import CardLayout from "../../layouts/CardLayout"; - -function GetStartedPage() { - return ( - -
    -
    -
    -

    Get started with Solana development

    - -
    -

    - Build and deploy your first on chain Solana program directly in - your browser. -

    - - - Get Started - -
    -
    - -
    -
    - - - - - - -
    -
    - -
    -

    Community Resources

    - -
    - - - - - -
    -
    -
    -
    -
    - ); -} - -export default GetStartedPage; diff --git a/docs/src/proposals.md b/docs/src/proposals.md index d2a6e9a325..61bd657ff3 100644 --- a/docs/src/proposals.md +++ b/docs/src/proposals.md @@ -1,5 +1,6 @@ --- title: System Design Proposals +sidebar_label: Overview --- Changes to the Solana architecture are performed through a public proposal process (via pull requests) on the [Solana GitHub repository](https://github.com/solana-labs/solana). New proposals should be submitted with the "[Submit a Design Proposal](#submit-a-design-proposal)" guide below. @@ -7,13 +8,13 @@ Changes to the Solana architecture are performed through a public proposal proce There are currently two different states of these design proposals: 1. [Accepted Proposals](./proposals/accepted-design-proposals.md) -2. [Implemented Proposals](./implemented-proposals/implemented-proposals.md) +2. [Implemented Proposals](./implemented-proposals/index.md) ## Accepted Proposals These architectural proposals have been accepted by the Solana team, but are not yet fully implemented. -Each proposal may be implemented as described, implemented differently as issues in the designs become evident, or not implemented at all. If implemented, the proposal will be moved to [Implemented Proposals](./implemented-proposals/implemented-proposals.md) and the details will be added to relevant sections of the docs. +Each proposal may be implemented as described, implemented differently as issues in the designs become evident, or not implemented at all. If implemented, the proposal will be moved to [Implemented Proposals](./implemented-proposals/index.md) and the details will be added to relevant sections of the docs. ## Implemented Proposals diff --git a/docs/src/proposals/accepted-design-proposals.md b/docs/src/proposals/accepted-design-proposals.md index e2145d26b6..61d2d2ef4f 100644 --- a/docs/src/proposals/accepted-design-proposals.md +++ b/docs/src/proposals/accepted-design-proposals.md @@ -8,7 +8,7 @@ These architectural proposals have been accepted by the Solana maintainers, but ## After Implemented -Once a proposal has been implemented, it will be moved to [Implemented Proposals](../implemented-proposals/implemented-proposals.md) and the details will be added to relevant sections of the docs. +Once a proposal has been implemented, it will be moved to [Implemented Proposals](../implemented-proposals/index.md) and the details will be added to relevant sections of the docs. ## Submit a New Proposal diff --git a/docs/src/proposals/bankless-leader.md b/docs/src/proposals/bankless-leader.md index eac7b990cc..462b253a33 100644 --- a/docs/src/proposals/bankless-leader.md +++ b/docs/src/proposals/bankless-leader.md @@ -2,58 +2,94 @@ title: Bankless Leader --- -A bankless leader does the minimum amount of work to produce a valid block. The leader is tasked with ingress transactions, sorting and filtering valid transactions, arranging them into entries, shredding the entries and broadcasting the shreds. While a validator only needs to reassemble the block and replay execution of well formed entries. The leader does 3x more memory operations before any bank execution than the validator per processed transaction. +A bankless leader does the minimum amount of work to produce a valid block. The +leader is tasked with ingress transactions, sorting and filtering valid +transactions, arranging them into entries, shredding the entries and +broadcasting the shreds. While a validator only needs to reassemble the block +and replay execution of well formed entries. The leader does 3x more memory +operations before any bank execution than the validator per processed +transaction. ## Rationale -Normal bank operation for a spend needs to do 2 loads and 2 stores. With this design leader just does 1 load. so 4x less account_db work before generating the block. The store operations are likely to be more expensive than reads. +Normal bank operation for a spend needs to do 2 loads and 2 stores. With this +design leader just does 1 load. so 4x less account_db work before generating the +block. The store operations are likely to be more expensive than reads. -When replay stage starts processing the same transactions, it can assume that PoH is valid, and that all the entries are safe for parallel execution. The fee accounts that have been loaded to produce the block are likely to still be in memory, so the additional load should be warm and the cost is likely to be amortized. +When replay stage starts processing the same transactions, it can assume that +PoH is valid, and that all the entries are safe for parallel execution. The fee +accounts that have been loaded to produce the block are likely to still be in +memory, so the additional load should be warm and the cost is likely to be +amortized. ## Fee Account -The [fee account](../terminology.md#fee_account) pays for the transaction to be included in the block. The leader only needs to validate that the fee account has the balance to pay for the fee. +The [fee account](https://solana.com/docs/terminology#fee_account) pays for the +transaction to be included in the block. The leader only needs to validate that +the fee account has the balance to pay for the fee. ## Balance Cache -For the duration of the leaders consecutive blocks, the leader maintains a temporary balance cache for all the processed fee accounts. The cache is a map of pubkeys to lamports. +For the duration of the leaders consecutive blocks, the leader maintains a +temporary balance cache for all the processed fee accounts. The cache is a map +of pubkeys to lamports. -At the start of the first block the balance cache is empty. At the end of the last block the cache is destroyed. +At the start of the first block the balance cache is empty. At the end of the +last block the cache is destroyed. -The balance cache lookups must reference the same base fork for the entire duration of the cache. At the block boundary, the cache can be reset along with the base fork after replay stage finishes verifying the previous block. +The balance cache lookups must reference the same base fork for the entire +duration of the cache. At the block boundary, the cache can be reset along with +the base fork after replay stage finishes verifying the previous block. ## Balance Check -Prior to the balance check, the leader validates all the signatures in the transaction. +Prior to the balance check, the leader validates all the signatures in the +transaction. 1. Verify the accounts are not in use and BlockHash is valid. -2. Check if the fee account is present in the cache, or load the account from accounts_db and store the lamport balance in the cache. +2. Check if the fee account is present in the cache, or load the account from + accounts_db and store the lamport balance in the cache. 3. If the balance is less than the fee, drop the transaction. 4. Subtract the fee from the balance. -5. For all the keys in the transaction that are Credit-Debit and are referenced by an instruction, reduce their balance to 0 in the cache. The account fee is declared as Credit-Debit, but as long as it is not used in any instruction its balance will not be reduced to 0. +5. For all the keys in the transaction that are Credit-Debit and are referenced + by an instruction, reduce their balance to 0 in the cache. The account fee is + declared as Credit-Debit, but as long as it is not used in any instruction + its balance will not be reduced to 0. ## Leader Replay -Leaders will need to replay their blocks as part of the standard replay stage operation. +Leaders will need to replay their blocks as part of the standard replay stage +operation. ## Leader Replay With Consecutive Blocks -A leader can be scheduled to produce multiple blocks in a row. In that scenario the leader is likely to be producing the next block while the replay stage for the first block is playing. +A leader can be scheduled to produce multiple blocks in a row. In that scenario +the leader is likely to be producing the next block while the replay stage for +the first block is playing. -When the leader finishes the replay stage it can reset the balance cache by clearing it, and set a new fork as the base for the cache which can become active on the next block. +When the leader finishes the replay stage it can reset the balance cache by +clearing it, and set a new fork as the base for the cache which can become +active on the next block. ## Resetting the Balance Cache -1. At the start of the block, if the balance cache is uninitialized, set the base fork for the balance cache to be the parent of the block and create an empty cache. -2. if the cache is initialized, check if block's parents has a new frozen bank that is newer than the current base fork for the balance cache. -3. if a parent newer than the cache's base fork exist, reset the cache to the parent. +1. At the start of the block, if the balance cache is uninitialized, set the + base fork for the balance cache to be the parent of the block and create an + empty cache. +2. if the cache is initialized, check if block's parents has a new frozen bank + that is newer than the current base fork for the balance cache. +3. if a parent newer than the cache's base fork exist, reset the cache to the + parent. ## Impact on Clients -The same fee account can be reused many times in the same block until it is used once as Credit-Debit by an instruction. +The same fee account can be reused many times in the same block until it is used +once as Credit-Debit by an instruction. -Clients that transmit a large number of transactions per second should use a dedicated fee account that is not used as Credit-Debit in any instruction. +Clients that transmit a large number of transactions per second should use a +dedicated fee account that is not used as Credit-Debit in any instruction. -Once an account fee is used as Credit-Debit, it will fail the balance check until the balance cache is reset. +Once an account fee is used as Credit-Debit, it will fail the balance check +until the balance cache is reset. ### Check out the [SIMD here to contribute](https://github.com/solana-foundation/solana-improvement-documents/pull/5) diff --git a/docs/src/proposals/blockstore-rocksdb-compaction.md b/docs/src/proposals/blockstore-rocksdb-compaction.md index be89214f73..85b7e3a8c4 100644 --- a/docs/src/proposals/blockstore-rocksdb-compaction.md +++ b/docs/src/proposals/blockstore-rocksdb-compaction.md @@ -22,7 +22,7 @@ required for storing each entry. In other words, RocksDB uses compactions to balance [write, space, and read amplifications](https://smalldatum.blogspot.com/2015/11/read-write-space-amplification-pick-2_23.html). As different workloads have different requirements, RocksDB makes its options -highly configerable. However, it also means its default settings might not +highly configurable. However, it also means its default settings might not be always suitable. This document focuses on RocksDB's compaction optimization for Solana's Blockstore. diff --git a/docs/src/proposals/tick-verification.md b/docs/src/proposals/tick-verification.md index 8be7ef939b..a84c42c985 100644 --- a/docs/src/proposals/tick-verification.md +++ b/docs/src/proposals/tick-verification.md @@ -18,12 +18,12 @@ number of hashes. Malicious transmissions `T` are handled in two ways: -1. If a leader can generate some erronenous transmission `T` and also some +1. If a leader can generate some erroneous transmission `T` and also some alternate transmission `T'` for the same slot without violating any slashing rules for duplicate transmissions (for instance if `T'` is a subset of `T`), then the cluster must handle the possibility of both transmissions being live. -Thus this means we cannot mark the erronenous transmission `T` as dead because +Thus this means we cannot mark the erroneous transmission `T` as dead because the cluster may have reached consensus on `T'`. These cases necessitate a slashing proof to punish this bad behavior. diff --git a/docs/src/running-validator.md b/docs/src/running-validator.md deleted file mode 100644 index 177cbdb19d..0000000000 --- a/docs/src/running-validator.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Running a Validator ---- - -This section describes how to run a Solana validator node. - -There are several clusters available to connect to; see [choosing a Cluster](cli/choose-a-cluster.md) for an overview of each. diff --git a/docs/src/developing/runtime-facilities/programs.md b/docs/src/runtime/programs.md similarity index 99% rename from docs/src/developing/runtime-facilities/programs.md rename to docs/src/runtime/programs.md index d53b96abc4..ae6b0127a2 100644 --- a/docs/src/developing/runtime-facilities/programs.md +++ b/docs/src/runtime/programs.md @@ -68,7 +68,7 @@ instruction via a program id, the Solana runtime will load both your the program and its owner, the BPF Upgradeable Loader. The runtime then passes your program to the BPF Upgradeable Loader to process the instruction. -[More information about deployment](cli/deploy-a-program.md) +[More information about deployment](../cli/examples/deploy-a-program.md) ## Ed25519 Program diff --git a/docs/src/developing/runtime-facilities/sysvars.md b/docs/src/runtime/sysvars.md similarity index 86% rename from docs/src/developing/runtime-facilities/sysvars.md rename to docs/src/runtime/sysvars.md index 908ecdafe5..99d271f0a3 100644 --- a/docs/src/developing/runtime-facilities/sysvars.md +++ b/docs/src/runtime/sysvars.md @@ -3,10 +3,9 @@ title: Sysvar Cluster Data --- Solana exposes a variety of cluster state data to programs via -[`sysvar`](terminology.md#sysvar) accounts. These accounts are populated at -known addresses published along with the account layouts in the -[`solana-program` -crate](https://docs.rs/solana-program/VERSION_FOR_DOCS_RS/solana_program/sysvar/index.html), +[`sysvar`](https://solana.com/docs/terminology#sysvar) accounts. These accounts +are populated at known addresses published along with the account layouts in the +[`solana-program` crate](https://docs.rs/solana-program/VERSION_FOR_DOCS_RS/solana_program/sysvar/index.html), and outlined below. There are two ways for a program to access a sysvar. @@ -18,21 +17,25 @@ let clock = Clock::get() ``` The following sysvars support `get`: + - Clock - EpochSchedule - Fees - Rent - EpochRewards -The second is to pass the sysvar to the program as an account by including its address as one of the accounts in the `Instruction` and then deserializing the data during execution. Access to sysvars accounts is -always _readonly_. +The second is to pass the sysvar to the program as an account by including its +address as one of the accounts in the `Instruction` and then deserializing the +data during execution. Access to sysvars accounts is always _readonly_. ``` let clock_sysvar_info = next_account_info(account_info_iter)?; let clock = Clock::from_account_info(&clock_sysvar_info)?; ``` -The first method is more efficient and does not require that the sysvar account be passed to the program, or specified in the `Instruction` the program is processing. +The first method is more efficient and does not require that the sysvar account +be passed to the program, or specified in the `Instruction` the program is +processing. ## Clock @@ -40,13 +43,17 @@ The Clock sysvar contains data on cluster time, including the current slot, epoch, and estimated wall-clock Unix timestamp. It is updated every slot. - Address: `SysvarC1ock11111111111111111111111111111111` -- Layout: [Clock](https://docs.rs/solana-program/VERSION_FOR_DOCS_RS/solana_program/clock/struct.Clock.html) +- Layout: + [Clock](https://docs.rs/solana-program/VERSION_FOR_DOCS_RS/solana_program/clock/struct.Clock.html) - Fields: - `slot`: the current slot - - `epoch_start_timestamp`: the Unix timestamp of the first slot in this epoch. In the first slot of an epoch, this timestamp is identical to the `unix_timestamp` (below). + - `epoch_start_timestamp`: the Unix timestamp of the first slot in this epoch. + In the first slot of an epoch, this timestamp is identical to the + `unix_timestamp` (below). - `epoch`: the current epoch - - `leader_schedule_epoch`: the most recent epoch for which the leader schedule has already been generated + - `leader_schedule_epoch`: the most recent epoch for which the leader schedule + has already been generated - `unix_timestamp`: the Unix timestamp of this slot. Each slot has an estimated duration based on Proof of History. But in reality, @@ -69,7 +76,8 @@ epoch, and estimated wall-clock Unix timestamp. It is updated every slot. The EpochSchedule sysvar contains epoch scheduling constants that are set in genesis, and enables calculating the number of slots in a given epoch, the epoch -for a given slot, etc. (Note: the epoch schedule is distinct from the [`leader schedule`](terminology.md#leader-schedule)) +for a given slot, etc. (Note: the epoch schedule is distinct from the +[`leader schedule`](https://solana.com/docs/terminology#leader-schedule)) - Address: `SysvarEpochSchedu1e111111111111111111111111` - Layout: @@ -159,7 +167,8 @@ determining whether epoch rewards distribution has finished. ## LastRestartSlot -The LastRestartSlot sysvar contains the slot number of the last restart or _0_ (zero) if none ever happened. +The LastRestartSlot sysvar contains the slot number of the last restart or _0_ +(zero) if none ever happened. - Address: `SysvarLastRestartS1ot1111111111111111111111` - Layout: diff --git a/docs/src/developing/runtime-facilities/zk-docs/ciphertext_ciphertext_equality.pdf b/docs/src/runtime/zk-docs/ciphertext_ciphertext_equality.pdf similarity index 100% rename from docs/src/developing/runtime-facilities/zk-docs/ciphertext_ciphertext_equality.pdf rename to docs/src/runtime/zk-docs/ciphertext_ciphertext_equality.pdf diff --git a/docs/src/developing/runtime-facilities/zk-docs/ciphertext_commitment_equality.pdf b/docs/src/runtime/zk-docs/ciphertext_commitment_equality.pdf similarity index 100% rename from docs/src/developing/runtime-facilities/zk-docs/ciphertext_commitment_equality.pdf rename to docs/src/runtime/zk-docs/ciphertext_commitment_equality.pdf diff --git a/docs/src/developing/runtime-facilities/zk-docs/pubkey_proof.pdf b/docs/src/runtime/zk-docs/pubkey_proof.pdf similarity index 100% rename from docs/src/developing/runtime-facilities/zk-docs/pubkey_proof.pdf rename to docs/src/runtime/zk-docs/pubkey_proof.pdf diff --git a/docs/src/developing/runtime-facilities/zk-docs/twisted_elgamal.pdf b/docs/src/runtime/zk-docs/twisted_elgamal.pdf similarity index 100% rename from docs/src/developing/runtime-facilities/zk-docs/twisted_elgamal.pdf rename to docs/src/runtime/zk-docs/twisted_elgamal.pdf diff --git a/docs/src/developing/runtime-facilities/zk-docs/zero_proof.pdf b/docs/src/runtime/zk-docs/zero_proof.pdf similarity index 100% rename from docs/src/developing/runtime-facilities/zk-docs/zero_proof.pdf rename to docs/src/runtime/zk-docs/zero_proof.pdf diff --git a/docs/src/developing/runtime-facilities/zk-token-proof.md b/docs/src/runtime/zk-token-proof.md similarity index 100% rename from docs/src/developing/runtime-facilities/zk-token-proof.md rename to docs/src/runtime/zk-token-proof.md diff --git a/docs/src/staking.md b/docs/src/staking.md deleted file mode 100644 index 312f44fd99..0000000000 --- a/docs/src/staking.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Staking on Solana ---- - -_Note before reading: All references to increases in values are in absolute -terms with regards to balance of SOL. -This document makes no suggestion as to the monetary value of SOL at any time._ - -By staking your SOL tokens, you help secure the network and -[earn rewards](implemented-proposals/staking-rewards.md) while doing so. - -You can stake by delegating your tokens to validators who process transactions and run the network. - -Delegating stake is a shared-risk shared-reward financial model that may provide -returns to holders of tokens delegated for a long period. -This is achieved by aligning the financial incentives of the token-holders -(delegators) and the validators to whom they delegate. - -The more stake delegated to a validator, the more often this validator -is chosen to write new transactions to the ledger. The more transactions -the validator writes, the more rewards the validator and its delegators earn. -Validators who configure their systems to be able to process more transactions -earn proportionally more rewards and -because they keep the network running as fast and as smoothly as possible. - -Validators incur costs by running and maintaining their systems, and this is -passed on to delegators in the form of a fee collected as a percentage of -rewards earned. This fee is known as a _commission_. Since validators earn more -rewards the more stake is delegated to them, they may compete with one another -to offer the lowest commission for their services. - -You risk losing tokens when staking through a process known as -_slashing_. 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. - -When a validator is slashed, all token holders who have delegated stake to that -validator lose a portion of their delegation. While this means an immediate -loss for the token holder, it also is a loss of future rewards for the validator -due to their reduced total delegation. More details on the slashing roadmap can -be found -[here](proposals/optimistic-confirmation-and-slashing.md#slashing-roadmap). - -Rewards and slashing align validator and token holder interests which helps keep the network -secure, robust and performant. - - -## How do I stake my SOL tokens? - -You can stake SOL by moving your tokens -into a wallet that supports staking. The wallet provides steps to create a stake account -and do the delegation. - -#### Supported Wallets - -Many web and mobile wallets support Solana staking operations. Please check with -your favorite wallet's maintainers regarding status - -#### Solana command line tools -- Solana command line tools can perform all stake operations in conjunction - with a CLI-generated keypair file wallet, a paper wallet, or with a connected - Ledger Nano. - [Staking commands using the Solana Command Line Tools](cli/delegate-stake.md). - -#### Create a Stake Account - -Follow the wallet's instructions for creating a staking account. This account -will be of a different type than one used to simply send and receive tokens. - -#### Select a Validator - -Follow the wallet's instructions for selecting a validator. You can get -information about potentially performant validators from the links below. -The Solana Foundation does not recommend any particular validator. - -The site solanabeach.io is built and maintained by one of our validators, -Staking Facilities. It provides a some high-level graphical information about -the network as a whole, as well as a list of each validator and some recent -performance statistics about each one. - -- https://solanabeach.io - -To view block production statistics, use the Solana command-line tools: - -- `solana validators` -- `solana block-production` - -The Solana team does not make recommendations on how to interpret this -information. Do your own due diligence. - -#### Delegate your Stake - -Follow the wallet's instructions for delegating your to your chosen validator. - -## Stake Account Details - -For more information about the operations and permissions associated with a -stake account, please see [Stake Accounts](staking/stake-accounts.md) diff --git a/docs/src/staking/stake-accounts.md b/docs/src/staking/stake-accounts.md deleted file mode 100644 index 0890bfb2ab..0000000000 --- a/docs/src/staking/stake-accounts.md +++ /dev/null @@ -1,141 +0,0 @@ ---- -title: Stake Account Structure ---- - -A stake account on Solana can be used to delegate tokens to validators on -the network to potentially earn rewards for the owner of the stake account. -Stake accounts are created and managed differently than a traditional wallet -address, known as a _system account_. A system account is only able to send and -receive SOL from other accounts on the network, whereas a stake account supports -more complex operations needed to manage a delegation of tokens. - -Stake accounts on Solana also work differently than those of other Proof-of-Stake -blockchain networks that you may be familiar with. This document describes the -high-level structure and functions of a Solana stake account. - -#### Account Address - -Each stake account has a unique address which can be used to look up the account -information in the command line or in any network explorer tools. However, -unlike a wallet address in which the holder of the address's keypair controls -the wallet, the keypair associated with a stake account address does not necessarily have -any control over the account. In fact, a keypair or private key may not even -exist for a stake account's address. - -The only time a stake account's address has a keypair file is when [creating -a stake account using the command line tools](../cli/delegate-stake.md#create-a-stake-account). -A new keypair file is created first only to ensure that the stake account's -address is new and unique. - -#### Understanding Account Authorities - -Certain types of accounts may have one or more _signing authorities_ -associated with a given account. An account authority is used to sign certain -transactions for the account it controls. This is different from -some other blockchain networks where the holder of the keypair associated with -the account's address controls all of the account's activity. - -Each stake account has two signing authorities specified by their respective address, -each of which is authorized to perform certain operations on the stake account. - -The _stake authority_ is used to sign transactions for the following operations: - -- Delegating stake -- Deactivating the stake delegation -- Splitting the stake account, creating a new stake account with a portion of the - funds in the first account -- Merging two stake accounts into one -- Setting a new stake authority - -The _withdraw authority_ signs transactions for the following: - -- Withdrawing un-delegated stake into a wallet address -- Setting a new withdraw authority -- Setting a new stake authority - -The stake authority and withdraw authority are set when the stake account is -created, and they can be changed to authorize a new signing address at any time. -The stake and withdraw authority can be the same address or two different -addresses. - -The withdraw authority keypair holds more control over the account as it is -needed to liquidate the tokens in the stake account, and can be used to reset -the stake authority if the stake authority keypair becomes lost or compromised. - -Securing the withdraw authority against loss or theft is of utmost importance -when managing a stake account. - -#### Multiple Delegations - -Each stake account may only be used to delegate to one validator at a time. -All of the tokens in the account are either delegated or un-delegated, or in the -process of becoming delegated or un-delegated. To delegate a fraction of your -tokens to a validator, or to delegate to multiple validators, you must create -multiple stake accounts. - -This can be accomplished by creating multiple stake accounts from a wallet -address containing some tokens, or by creating a single large stake account -and using the stake authority to split the account into multiple accounts -with token balances of your choosing. - -The same stake and withdraw authorities can be assigned to multiple -stake accounts. - -#### Merging stake accounts - -Two stake accounts that have the same authorities and lockup can be merged into -a single resulting stake account. A merge is possible between two stakes in the -following states with no additional conditions: - -- two deactivated stakes -- an inactive stake into an activating stake during its activation epoch - -For the following cases, the voter pubkey and vote credits observed must match: - -- two activated stakes -- two activating accounts that share an activation epoch, during the activation epoch - -All other combinations of stake states will fail to merge, including all "transient" -states, where a stake is activating or deactivating with a non-zero effective stake. - -#### Delegation Warmup and Cooldown - -When a stake account is delegated, or a delegation is deactivated, the operation -does not take effect immediately. - -A delegation or deactivation takes several [epochs](../terminology.md#epoch) -to complete, with a fraction of the delegation becoming active or inactive at -each epoch boundary after the transaction containing the instructions has been -submitted to the cluster. - -There is also a limit on how much total stake can become delegated or -deactivated in a single epoch, to prevent large sudden changes in stake across -the network as a whole. Since warmup and cooldown are dependent on the behavior -of other network participants, their exact duration is difficult to predict. -Details on the warmup and cooldown timing can be found -[here](../cluster/stake-delegation-and-rewards.md#stake-warmup-cooldown-withdrawal). - -#### Lockups - -Stake accounts can have a lockup which prevents the tokens they hold from being -withdrawn before a particular date or epoch has been reached. While locked up, -the stake account can still be delegated, un-delegated, or split, and its stake -authority can be changed as normal. Only withdrawal into another wallet or -updating the withdraw authority is not allowed. - -A lockup can only be added when a stake account is first created, but it can be -modified later, by the _lockup authority_ or _custodian_, the address of which -is also set when the account is created. - -#### Destroying a Stake Account - -Like other types of accounts on the Solana network, a stake account that has a -balance of 0 SOL is no longer tracked. If a stake account is not delegated -and all of the tokens it contains are withdrawn to a wallet address, the account -at that address is effectively destroyed, and will need to be manually -re-created for the address to be used again. - -#### Viewing Stake Accounts - -Stake account details can be viewed on the [Solana Explorer](http://explorer.solana.com/accounts) -by copying and pasting an account address into the search bar. diff --git a/docs/src/staking/stake-programming.md b/docs/src/staking/stake-programming.md deleted file mode 100644 index 99dace2cd9..0000000000 --- a/docs/src/staking/stake-programming.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Stake Programming ---- - -To maximize stake distribution, decentralization, and censorship resistance on -the Solana network, staking can be performed programmatically. The team -and community have developed several on-chain and off-chain programs to make -stakes easier to manage. - -#### Stake-o-matic aka Auto-delegation Bots - -This off-chain program manages a large population of validators staked by a -central authority. The Solana Foundation uses an auto-delegation bot to regularly delegate its -stake to "non-delinquent" validators that meet specified performance requirements. - -#### Stake Pools - -This on-chain program pools together SOL to be staked by a manager, allowing SOL -holders to stake and earn rewards without managing stakes. -Users deposit SOL in exchange for SPL tokens (staking derivatives) that represent their ownership in the stake pool. The pool -manager stakes deposited SOL according to their strategy, perhaps using a variant -of an auto-delegation bot as described above. As stakes earn rewards, the pool and pool tokens -grow proportionally in value. Finally, pool token holders can send SPL tokens -back to the stake pool to redeem SOL, thereby participating in decentralization with much -less work required. More information can be found at the -[SPL stake pool documentation](https://spl.solana.com/stake-pool). diff --git a/docs/src/storage_rent_economics.md b/docs/src/storage_rent_economics.md deleted file mode 100644 index 4b65b250e1..0000000000 --- a/docs/src/storage_rent_economics.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Storage Rent Economics ---- - -Each transaction that is submitted to the Solana ledger imposes costs. -Transaction fees paid by the submitter, and collected by a validator, in -theory, account for the acute, transactional, costs of validating and adding -that data to the ledger. Unaccounted in this process is the mid-term storage of -active ledger state, necessarily maintained by the rotating validator set. This -type of storage imposes costs not only to validators but also to the broader -network as active state grows so does data transmission and validation -overhead. To account for these costs, we describe here our preliminary design -and implementation of storage rent. - -Storage rent can be paid via one of two methods: - -Method 1: Set it and forget it - -With this approach, accounts with two-years worth of rent deposits secured are -exempt from network rent charges. By maintaining this minimum-balance, the -broader network benefits from reduced liquidity and the account holder can rest -assured that their `Account::data` will be retained for continual access/usage. - -Method 2: Pay per byte - -If an account has less than two-years worth of deposited rent the network -charges rent on a per-epoch basis, in credit for the next epoch. This rent is -deducted at a rate specified in genesis, in lamports per kilobyte-year. - -For information on the technical implementation details of this design, see the -[Rent](implemented-proposals/rent.md) section. - -**Note:** New accounts now **are required** to be initialized with enough -lamports to be rent exempt. Additionally, transactions that leave an account's -balance below the rent exempt minimum (and non-zero) will **fail**. This -essentially renders all accounts rent exempt. Rent-paying accounts that were -created before this requirement will continue paying rent until either (1) -their balance falls to zero, or (2) a transaction increases the account's -balance to be rent exempt. diff --git a/docs/src/terminology.md b/docs/src/terminology.md deleted file mode 100644 index 4bb8efdbbf..0000000000 --- a/docs/src/terminology.md +++ /dev/null @@ -1,404 +0,0 @@ ---- -title: Terminology -description: "Learn the essential terminology used throughout the Solana blockchain and development models." -keywords: - - terms - - dictionary - - definitions - - define - - programming models ---- - -The following terms are used throughout the Solana documentation and development ecosystem. - -## account - -A record in the Solana ledger that either holds data or is an executable program. - -Like an account at a traditional bank, a Solana account may hold funds called [lamports](#lamport). Like a file in Linux, it is addressable by a key, often referred to as a [public key](#public-key-pubkey) or pubkey. - -The key may be one of: - -- an ed25519 public key -- a program-derived account address (32byte value forced off the ed25519 curve) -- a hash of an ed25519 public key with a 32 character string - -## account owner - -The address of the program that owns the account. Only the owning program is capable of modifying the account. - -## app - -A front-end application that interacts with a Solana cluster. - -## bank state - -The result of interpreting all programs on the ledger at a given [tick height](#tick-height). It includes at least the set of all [accounts](#account) holding nonzero [native tokens](#native-token). - -## block - -A contiguous set of [entries](#entry) on the ledger covered by a [vote](#ledger-vote). A [leader](#leader) produces at most one block per [slot](#slot). - -## blockhash - -A unique value ([hash](#hash)) that identifies a record (block). Solana computes a blockhash from the last [entry id](#entry-id) of the block. - -## block height - -The number of [blocks](#block) beneath the current block. The first block after the [genesis block](#genesis-block) has height one. - -## bootstrap validator - -The [validator](#validator) that produces the genesis (first) [block](#block) of a block chain. - -## BPF loader - -The Solana program that owns and loads [BPF](developing/on-chain-programs/faq#berkeley-packet-filter-bpf) smart contract programs, allowing the program to interface with the runtime. - -## client - -A computer program that accesses the Solana server network [cluster](#cluster). - -## commitment - -A measure of the network confirmation for the [block](#block). - -## cluster - -A set of [validators](#validator) maintaining a single [ledger](#ledger). - -## compute budget - -The maximum number of [compute units](#compute-units) consumed per transaction. - -## compute units - -The smallest unit of measure for consumption of computational resources of the blockchain. - -## confirmation time - -The wallclock duration between a [leader](#leader) creating a [tick entry](#tick) and creating a [confirmed block](#confirmed-block). - -## confirmed block - -A [block](#block) that has received a [super majority](#supermajority) of [ledger votes](#ledger-vote). - -## control plane - -A gossip network connecting all [nodes](#node) of a [cluster](#cluster). - -## cooldown period - -Some number of [epochs](#epoch) after [stake](#stake) has been deactivated while it progressively becomes available for withdrawal. During this period, the stake is considered to be "deactivating". More info about: [warmup and cooldown](implemented-proposals/staking-rewards.md#stake-warmup-cooldown-withdrawal) - -## credit - -See [vote credit](#vote-credit). - -## cross-program invocation (CPI) - -A call from one smart contract program to another. For more information, see [calling between programs](developing/programming-model/calling-between-programs.md). - -## data plane - -A multicast network used to efficiently validate [entries](#entry) and gain consensus. - -## drone - -An off-chain service that acts as a custodian for a user's private key. It typically serves to validate and sign transactions. - -## entry - -An entry on the [ledger](#ledger) either a [tick](#tick) or a [transaction's entry](#transactions-entry). - -## entry id - -A preimage resistant [hash](#hash) over the final contents of an entry, which acts as the [entry's](#entry) globally unique identifier. The hash serves as evidence of: - -- The entry being generated after a duration of time -- The specified [transactions](#transaction) are those included in the entry -- The entry's position with respect to other entries in [ledger](#ledger) - -See [proof of history](#proof-of-history-poh). - -## epoch - -The time, i.e. number of [slots](#slot), for which a [leader schedule](#leader-schedule) is valid. - -## fee account - -The fee account in the transaction is the account that pays for the cost of including the transaction in the ledger. This is the first account in the transaction. This account must be declared as Read-Write (writable) in the transaction since paying for the transaction reduces the account balance. - -## finality - -When nodes representing 2/3rd of the [stake](#stake) have a common [root](#root). - -## fork - -A [ledger](#ledger) derived from common entries but then diverged. - -## genesis block - -The first [block](#block) in the chain. - -## genesis config - -The configuration file that prepares the [ledger](#ledger) for the [genesis block](#genesis-block). - -## hash - -A digital fingerprint of a sequence of bytes. - -## inflation - -An increase in token supply over time used to fund rewards for validation and to fund continued development of Solana. - -## inner instruction - -See [cross-program invocation](#cross-program-invocation-cpi). - -## instruction - -The smallest contiguous unit of execution logic in a [program](#program). An instruction specifies which program it is calling, which accounts it wants to read or modify, and additional data that serves as auxiliary input to the program. A [client](#client) can include one or multiple instructions in a [transaction](#transaction). An instruction may contain one or more [cross-program invocations](#cross-program-invocation-cpi). - -## keypair - -A [public key](#public-key-pubkey) and corresponding [private key](#private-key) for accessing an account. - -## lamport - -A fractional [native token](#native-token) with the value of 0.000000001 [sol](#sol). - -:::info -Within the compute budget, a quantity of _[micro-lamports](https://github.com/solana-labs/solana/blob/ced8f6a512c61e0dd5308095ae8457add4a39e94/program-runtime/src/prioritization_fee.rs#L1-L2)_ is used in the calculation of [prioritization fees](#prioritization-fee). -::: - -## leader - -The role of a [validator](#validator) when it is appending [entries](#entry) to the [ledger](#ledger). - -## leader schedule - -A sequence of [validator](#validator) [public keys](#public-key-pubkey) mapped to [slots](#slot). The cluster uses the leader schedule to determine which validator is the [leader](#leader) at any moment in time. - -## ledger - -A list of [entries](#entry) containing [transactions](#transaction) signed by [clients](#client). -Conceptually, this can be traced back to the [genesis block](#genesis-block), but an actual [validator](#validator)'s ledger may have only newer [blocks](#block) to reduce storage, as older ones are not needed for validation of future blocks by design. - -## ledger vote - -A [hash](#hash) of the [validator's state](#bank-state) at a given [tick height](#tick-height). It comprises a [validator's](#validator) affirmation that a [block](#block) it has received has been verified, as well as a promise not to vote for a conflicting [block](#block) \(i.e. [fork](#fork)\) for a specific amount of time, the [lockout](#lockout) period. - -## light client - -A type of [client](#client) that can verify it's pointing to a valid [cluster](#cluster). It performs more ledger verification than a [thin client](#thin-client) and less than a [validator](#validator). - -## loader - -A [program](#program) with the ability to interpret the binary encoding of other on-chain programs. - -## lockout - -The duration of time for which a [validator](#validator) is unable to [vote](#ledger-vote) on another [fork](#fork). - -## message - -The structured contents of a [transaction](#transaction). Generally containing a header, array of account addresses, recent [blockhash](#blockhash), and an array of [instructions](#instruction). - -Learn more about the [message formatting inside of transactions](./developing/programming-model/transactions.md#message-format) here. - -## native token - -The [token](#token) used to track work done by [nodes](#node) in a cluster. - -## node - -A computer participating in a [cluster](#cluster). - -## node count - -The number of [validators](#validator) participating in a [cluster](#cluster). - -## PoH - -See [Proof of History](#proof-of-history-poh). - -## point - -A weighted [credit](#credit) in a rewards regime. In the [validator](#validator) [rewards regime](cluster/stake-delegation-and-rewards.md), the number of points owed to a [stake](#stake) during redemption is the product of the [vote credits](#vote-credit) earned and the number of lamports staked. - -## private key - -The private key of a [keypair](#keypair). - -## program - -The executable code that interprets the [instructions](#instruction) sent inside of each [transaction](#transaction) on the Solana. These programs are often referred to as "[_smart contracts_](./developing//intro/programs.md)" on other blockchains. - -## program derived account (PDA) - -An account whose signing authority is a program and thus is not controlled by a private key like other accounts. - -## program id - -The public key of the [account](#account) containing a [program](#program). - -## proof of history (PoH) - -A stack of proofs, each of which proves that some data existed before the proof was created and that a precise duration of time passed before the previous proof. Like a [VDF](#verifiable-delay-function-vdf), a Proof of History can be verified in less time than it took to produce. - -## prioritization fee - -An additional fee user can specify in the compute budget [instruction](#instruction) to prioritize their [transactions](#transaction). - -The prioritization fee is calculated by multiplying the requested maximum compute units by the compute-unit price (specified in increments of 0.000001 lamports per compute unit) rounded up to the nearest lamport. - -Transactions should request the minimum amount of compute units required for execution to minimize fees. - -## public key (pubkey) - -The public key of a [keypair](#keypair). - -## rent - -Fee paid by [Accounts](#account) and [Programs](#program) to store data on the blockchain. When accounts do not have enough balance to pay rent, they may be Garbage Collected. - -See also [rent exempt](#rent-exempt) below. Learn more about rent here: [What is rent?](../src/developing/intro/rent.md). - -## rent exempt - -Accounts that maintain more than 2 years with of rent payments in their account are considered "_rent exempt_" and will not incur the [collection of rent](../src/developing/intro/rent.md#collecting-rent). - -## root - -A [block](#block) or [slot](#slot) that has reached maximum [lockout](#lockout) on a [validator](#validator). The root is the highest block that is an ancestor of all active forks on a validator. All ancestor blocks of a root are also transitively a root. Blocks that are not an ancestor and not a descendant of the root are excluded from consideration for consensus and can be discarded. - -## runtime - -The component of a [validator](#validator) responsible for [program](#program) execution. - -## Sealevel - -Solana's parallel smart contracts run-time. - -## shred - -A fraction of a [block](#block); the smallest unit sent between [validators](#validator). - -## signature - -A 64-byte ed25519 signature of R (32-bytes) and S (32-bytes). With the requirement that R is a packed Edwards point not of small order and S is a scalar in the range of 0 <= S < L. -This requirement ensures no signature malleability. Each transaction must have at least one signature for [fee account](terminology#fee-account). -Thus, the first signature in transaction can be treated as [transaction id](#transaction-id) - -## skip rate -The percentage of [skipped slots](#skipped-slot) out of the total leader slots in the current epoch. This metric can be misleading as it has high variance after the epoch boundary when the sample size is small, as well as for validators with a low number of leader slots, however can also be useful in identifying node misconfigurations at times. - -## skipped slot - -A past [slot](#slot) that did not produce a [block](#block), because the leader was offline or the [fork](#fork) containing the slot was abandoned for a better alternative by cluster consensus. A skipped slot will not appear as an ancestor for blocks at subsequent slots, nor increment the [block height](terminology#block-height), nor expire the oldest `recent_blockhash`. - -Whether a slot has been skipped can only be determined when it becomes older than the latest [rooted](#root) (thus not-skipped) slot. - -## slot - -The period of time for which each [leader](#leader) ingests transactions and produces a [block](#block). - -Collectively, slots create a logical clock. Slots are ordered sequentially and non-overlapping, comprising roughly equal real-world time as per [PoH](#proof-of-history-poh). - -## smart contract - -A program on a blockchain that can read and modify accounts over which it has control. - -## sol - -The [native token](#native-token) of a Solana [cluster](#cluster). - -## Solana Program Library (SPL) - -A [library of programs](https://spl.solana.com/) on Solana such as spl-token that facilitates tasks such as creating and using tokens. - -## stake - -Tokens forfeit to the [cluster](#cluster) if malicious [validator](#validator) behavior can be proven. - -## supermajority - -2/3 of a [cluster](#cluster). - -## sysvar - -A system [account](#account). [Sysvars](developing/runtime-facilities/sysvars.md) provide cluster state information such as current tick height, rewards [points](#point) values, etc. Programs can access Sysvars via a Sysvar account (pubkey) or by querying via a syscall. - -## thin client - -A type of [client](#client) that trusts it is communicating with a valid [cluster](#cluster). - -## tick - -A ledger [entry](#entry) that estimates wallclock duration. - -## tick height - -The Nth [tick](#tick) in the [ledger](#ledger). - -## token - -A digitally transferable asset. - -## tps - -[Transactions](#transaction) per second. - -## tpu - -[Transaction processing unit](validator/tpu.md). - -## transaction - -One or more [instructions](#instruction) signed by a [client](#client) using one or more [keypairs](#keypair) and executed atomically with only two possible outcomes: success or failure. - -## transaction id - -The first [signature](#signature) in a [transaction](#transaction), which can be used to uniquely identify the transaction across the complete [ledger](#ledger). - -## transaction confirmations - -The number of [confirmed blocks](#confirmed-block) since the transaction was accepted onto the [ledger](#ledger). A transaction is finalized when its block becomes a [root](#root). - -## transactions entry - -A set of [transactions](#transaction) that may be executed in parallel. - -## tvu - -[Transaction validation unit](validator/tvu.md). - -## validator - -A full participant in a Solana network [cluster](#cluster) that produces new [blocks](#block). A validator validates the transactions added to the [ledger](#ledger) - -## VDF - -See [verifiable delay function](#verifiable-delay-function-vdf). - -## verifiable delay function (VDF) - -A function that takes a fixed amount of time to execute that produces a proof that it ran, which can then be verified in less time than it took to produce. - -## vote - -See [ledger vote](#ledger-vote). - -## vote credit - -A reward tally for [validators](#validator). A vote credit is awarded to a validator in its vote account when the validator reaches a [root](#root). - -## wallet - -A collection of [keypairs](#keypair) that allows users to manage their funds. - -## warmup period - -Some number of [epochs](#epoch) after [stake](#stake) has been delegated while it progressively becomes effective. During this period, the stake is considered to be "activating". More info about: [warmup and cooldown](cluster/stake-delegation-and-rewards.md#stake-warmup-cooldown-withdrawal) diff --git a/docs/src/transaction_fees.md b/docs/src/transaction_fees.md deleted file mode 100644 index e3a65fb930..0000000000 --- a/docs/src/transaction_fees.md +++ /dev/null @@ -1,234 +0,0 @@ ---- -title: Transaction Fees -description: - "Transaction fees are the small fees paid to process instructions on the - network. These fees are based on computation and an optional prioritization - fee." -keywords: - - instruction fee - - processing fee - - storage fee - - low fee blockchain - - gas - - gwei - - cheap network - - affordable blockchain ---- - -The small fees paid to process [instructions](./terminology.md#instruction) on -the Solana blockchain are known as "_transaction fees_". - -As each transaction (which contains one or more instructions) is sent through -the network, it gets processed by the current leader validation-client. Once -confirmed as a global state transaction, this _transaction fee_ is paid to the -network to help support the [economic design](#economic-design) of the Solana -blockchain. - -> **NOTE:** Transaction fees are different from -> [account rent](./terminology.md#rent)! While transaction fees are paid to -> process instructions on the Solana network, rent is paid to store data on the -> blockchain. - -> You can learn more about rent here: -> [What is rent?](./developing/intro/rent.md) - -## Why pay transaction fees? - -Transaction fees offer many benefits in the Solana -[economic design](#basic-economic-design) described below. Mainly: - -- they provide compensation to the validator network for the CPU/GPU resources - necessary to process transactions, -- reduce network spam by introducing real cost to transactions, -- and provide long-term economic stability to the network through a - protocol-captured minimum fee amount per transaction - -> **NOTE:** Network consensus votes are sent as normal system transfers, which -> means that validators pay transaction fees to participate in consensus. - -## Basic economic design - -Many blockchain networks \(e.g. Bitcoin and Ethereum\), rely on inflationary -_protocol-based rewards_ to secure the network in the short-term. Over the -long-term, these networks will increasingly rely on _transaction fees_ to -sustain security. - -The same is true on Solana. Specifically: - -- A fixed proportion (initially 50%) of each transaction fee is _burned_ - (destroyed), with the remaining going to the current - [leader](./terminology.md#leader) processing the transaction. -- A scheduled global inflation rate provides a source for - [rewards](./implemented-proposals/staking-rewards.md) distributed to - [Solana Validators](../src/running-validator.md). - -### Why burn some fees? - -As mentioned above, a fixed proportion of each transaction fee is _burned_ -(destroyed). This is intended to cement the economic value of SOL and thus -sustain the network's security. Unlike a scheme where transactions fees are -completely burned, leaders are still incentivized to include as many -transactions as possible in their slots. - -Burnt fees can also help prevent malicious validators from censoring -transactions by being considered in [fork](./terminology.md#fork) selection. - -#### Example of an attack: - -In the case of a [Proof of History (PoH)](./terminology.md#proof-of-history-poh) -fork with a malicious, censoring leader: - -- due to the fees lost from censoring, we would expect the total fees burned to - be **_less than_** a comparable honest fork -- if the censoring leader is to compensate for these lost protocol fees, they - would have to replace the burnt fees on their fork themselves -- thus potentially reducing the incentive to censor in the first place - -## Calculating transaction fees - -Transactions fees are calculated based on two main parts: - -- a statically set base fee per signature, and -- the computational resources used during the transaction, measured in - "[_compute units_](./terminology.md#compute-units)" - -Since each transaction may require a different amount of computational -resources, they are alloted a maximum number of _compute units_ per transaction -known as the "[_compute budget_](./terminology.md#compute-budget)". - -The execution of each instruction within a transaction consumes a different -number of _compute units_. After the maximum number of _compute units_ has been -consumed (aka compute budget exhaustion), the runtime will halt the transaction -and return an error. This results in a failed transaction. - -> **Learn more:** compute units and the -> [Compute Budget](./developing/programming-model/runtime#compute-budget) in the -> Runtime and [requesting a fee estimate](../api/http#getfeeformessage) from the -> RPC. - -## Prioritization fee - -A Solana transaction can include an **optional** fee to prioritize itself -against others known as a -"_[prioritization fee](./terminology.md#prioritization-fee)_". Paying this -additional fee helps boost how a transaction is prioritized against others, -resulting in faster execution times. - -### How the prioritization fee is calculated - -A transaction's [prioritization fee](./terminology.md#prioritization-fee) is -calculated by multiplying the maximum number of **_compute units_** by the -**_compute unit price_** (measured in _micro-lamports_). - -Each transaction can set the maximum number of compute units it is allowed to -consume and the compute unit price by including a `SetComputeUnitLimit` and -`SetComputeUnitPrice` compute budget instruction respectively. - -:::info -[Compute Budget instructions](https://github.com/solana-labs/solana/blob/master/sdk/src/compute_budget.rs) -do **not** require any accounts. ::: - -If no `SetComputeUnitLimit` instruction is provided, the limit will be -calculated as the product of the number of instructions in the transaction and -the default per-instruction units, which is currently -[200k](https://github.com/solana-labs/solana/blob/4293f11cf13fc1e83f1baa2ca3bb2f8ea8f9a000/program-runtime/src/compute_budget.rs#L13). - -If no `SetComputeUnitPrice` instruction is provided, the transaction will -default to no additional elevated fee and the lowest priority. - -### How to set the prioritization fee - -A transaction's prioritization fee is set by including a `SetComputeUnitPrice` -instruction, and optionally a `SetComputeUnitLimit` instruction. The runtime -will use these values to calculate the prioritization fee, which will be used to -prioritize the given transaction within the block. - -You can craft each of these instructions via their `rust` or `@solana/web3.js` -functions. Each of these instructions can then be included in the transaction -and sent to the cluster like normal. See also the -[best practices](#prioritization-fee-best-practices) below. - -:::caution Transactions can only contain **one of each type** of compute budget -instruction. Duplicate types will result in an -[`TransactionError::DuplicateInstruction`](https://github.com/solana-labs/solana/blob/master/sdk/src/transaction/error.rs#L144-145) -error, and ultimately transaction failure. ::: - -#### Rust - -The rust `solana-sdk` crate includes functions within -[`ComputeBudgetInstruction`](https://docs.rs/solana-sdk/latest/solana_sdk/compute_budget/enum.ComputeBudgetInstruction.html) -to craft instructions for setting the _compute unit limit_ and _compute unit -price_: - -```rust -let instruction = ComputeBudgetInstruction::set_compute_unit_limit(300_000); -``` - -```rust -let instruction = ComputeBudgetInstruction::set_compute_unit_price(1); -``` - -#### Javascript - -The `@solana/web3.js` library includes functions within the -[`ComputeBudgetProgram`](https://solana-labs.github.io/solana-web3.js/classes/ComputeBudgetProgram.html) -class to craft instructions for setting the _compute unit limit_ and _compute -unit price_: - -```js -const instruction = ComputeBudgetProgram.setComputeUnitLimit({ - units: 300_000, -}); -``` - -```js -const instruction = ComputeBudgetProgram.setComputeUnitPrice({ - microLamports: 1, -}); -``` - -### Prioritization fee best practices - -#### Request the minimum compute units - -Transactions should request the minimum amount of compute units required for -execution to minimize fees. Also note that fees are not adjusted when the number -of requested compute units exceeds the number of compute units actually consumed -by an executed transaction. - -#### Get recent prioritization fees - -Prior to sending a transaction to the cluster, you can use the -[`getRecentPrioritizationFees`](/api/http#getrecentprioritizationfees) RPC -method to get a list of the recent paid prioritization fees within the recent -blocks processed by the node. - -You could then use this data to estimate an appropriate prioritization fee for -your transaction to both (a) better ensure it gets processed by the cluster and -(b) minimize the fees paid. - -## Fee Collection - -Transactions are required to have at least one account which has signed the -transaction and is writable. Writable signer accounts are serialized first in -the list of transaction accounts and the first of these accounts is always used -as the "fee payer". - -Before any transaction instructions are processed, the fee payer account balance -will be deducted to pay for transaction fees. If the fee payer balance is not -sufficient to cover transaction fees, the transaction will be dropped by the -cluster. If the balance was sufficient, the fees will be deducted whether the -transaction is processed successfully or not. In fact, if any of the transaction -instructions return an error or violate runtime restrictions, all account -changes _except_ the transaction fee deduction will be rolled back. - -## Fee Distribution - -Transaction fees are partially burned and the remaining fees are collected by -the validator that produced the block that the corresponding transactions were -included in. The transaction fee burn rate was initialized as 50% when inflation -rewards were enabled at the beginning of 2021 and has not changed so far. These -fees incentivize a validator to process as many transactions as possible during -its slots in the leader schedule. Collected fees are deposited in the -validator's account (listed in the leader schedule for the current slot) after -processing all of the transactions included in a block. diff --git a/docs/src/validator/anatomy.md b/docs/src/validator/anatomy.md index 849e8a57a9..5a61eeff7e 100644 --- a/docs/src/validator/anatomy.md +++ b/docs/src/validator/anatomy.md @@ -1,5 +1,7 @@ --- title: Anatomy of a Validator +sidebar_label: Anatomy +sidebar_position: 1 --- ![Validator block diagrams](/img/validator.svg) diff --git a/docs/src/validator/best-practices/operations.md b/docs/src/validator/best-practices/operations.md deleted file mode 100644 index 0588fc9ee9..0000000000 --- a/docs/src/validator/best-practices/operations.md +++ /dev/null @@ -1,148 +0,0 @@ ---- -title: Validator Operations Best Practices -sidebar_label: General Operations ---- - -After you have successfully setup and started a [validator on testnet](../get-started/setup-a-validator.md) (or another cluster of your choice), you will want to become familiar with how to operate your validator on a day-to-day basis. During daily operations, you will be [monitoring your server](./monitoring.md), updating software regularly (both the Solana validator software and operating system packages), and managing your vote account and identity account. - -All of these skills are critical to practice. Maximizing your validator uptime is an important part of being a good operator. - -## Educational Workshops - -The Solana validator community holds regular educational workshops. You can watch past workshops through the [solana validator educational workshops playlist](https://www.youtube.com/watch?v=86zySQ5vGW8&list=PLilwLeBwGuK6jKrmn7KOkxRxS9tvbRa5p). - -## Help with the validator command line - -From within the Solana CLI, you can execute the `solana-validator` command with the `--help` flag to get a better understanding of the flags and sub commands available. - -``` -solana-validator --help -``` - -## Restarting your validator - -There are many operational reasons you may want to restart your validator. As a best practice, you should avoid a restart during a leader slot. A [leader slot](../../terminology.md#leader-schedule) is the time when your validator is expected to produce blocks. For the health of the cluster and also for your validator's ability to earn transaction fee rewards, you do not want your validator to be offline during an opportunity to produce blocks. - -To see the full leader schedule for an epoch, use the following command: - -``` -solana leader-schedule -``` - -Based on the current slot and the leader schedule, you can calculate open time windows where your validator is not expected to produce blocks. - -Assuming you are ready to restart, you may use the `solana-validator exit` command. The command exits your validator process when an appropriate idle time window is reached. Assuming that you have systemd implemented for your validator process, the validator should restart automatically after the exit. See the below help command for details: - -``` -solana-validator exit --help -``` - -## Upgrading - -There are many ways to upgrade the [Solana software](../../cli/install-solana-cli-tools.md). As an operator, you will need to upgrade often, so it is important to get comfortable with this process. - -> **Note** validator nodes do not need to be offline while the newest version is being downloaded or built from source. All methods below can be done before the validator process is restarted. - -### Building From Source - -It is a best practice to always build your Solana binaries from source. If you build from source, you are certain that the code you are building has not been tampered with before the binary was created. You may also be able to optimize your `solana-validator` binary to your specific hardware. - -If you build from source on the validator machine (or a machine with the same CPU), you can target your specific architecture using the `-march` flag. Refer to the Solana docs for [instructions on building from source](../../cli/install-solana-cli-tools.md#build-from-source). - -### solana-install - -If you are not comfortable building from source, or you need to quickly install a new version to test something out, you could instead try using the `solana-install` command. - -Assuming you want to install Solana version `1.14.17`, you would execute the following: - -``` -solana-install init 1.14.17 -``` - -This command downloads the executable for `1.14.17` and installs it into a `.local` directory. You can also look at `solana-install --help` for more options. - -> **Note** this command only works if you already have the solana cli installed. If you do not have the cli installed, refer to [install solana cli tools](../../cli/install-solana-cli-tools.md) - -### Restart - -For all install methods, the validator process will need to be restarted before the newly installed version is in use. Use `solana-validator exit` to restart your validator process. - -### Verifying version - -The best way to verify that your validator process has changed to the desired version is to grep the logs after a restart. The following grep command should show you the version that your validator restarted with: - -``` -grep -B1 'Starting validator with' -``` - -## Snapshots - -Validators operators who have not experienced significant downtime (multiple hours of downtime), should avoid downloading snapshots. It is important for the health of the cluster as well as your validator history to maintain the local ledger. Therefore, you should not download a new snapshot any time your validator is offline or experiences an issue. Downloading a snapshot should only be reserved for occasions when you do not have local state. Prolonged downtime or the first install of a new validator are examples of times when you may not have state locally. In other cases such as restarts for upgrades, a snapshot download should be avoided. - -To avoid downloading a snapshot on restart, add the following flag to the `solana-validator` command: - -``` ---no-snapshot-fetch -``` - -If you use this flag with the `solana-validator` command, make sure that you run `solana catchup ` after your validator starts to make sure that the validator is catching up in a reasonable time. After some time (potentially a few hours), if it appears that your validator continues to fall behind, then you may have to download a new snapshot. - -### Downloading Snapshots - -If you are starting a validator for the first time, or your validator has fallen too far behind after a restart, then you may have to download a snapshot. - -To download a snapshot, you must **_NOT_** use the `--no-snapshot-fetch` flag. Without the flag, your validator will automatically download a snapshot from your known validators that you specified with the `--known-validator` flag. - -If one of the known validators is downloading slowly, you can try adding the `--minimal-snapshot-download-speed` flag to your validator. This flag will switch to another known validator if the initial download speed is below the threshold that you set. - -### Manually Downloading Snapshots - -In the case that there are network troubles with one or more of your known validators, then you may have to manually download the snapshot. To manually download a snapshot from one of your known validators, first, find the IP address of the validator in using the `solana gossip` command. In the example below, `5D1fNXzvv5NjV1ysLjirC4WY92RNsVH18vjmcszZd8on` is the pubkey of one of my known validators: - -``` -solana gossip | grep 5D1fNXzvv5NjV1ysLjirC4WY92RNsVH18vjmcszZd8on -``` - -The IP address of the validators is `139.178.68.207` and the open port on this validator is `80`. You can see the IP address and port in the fifth column in the gossip output: - -``` -139.178.68.207 | 5D1fNXzvv5NjV1ysLjirC4WY92RNsVH18vjmcszZd8on | 8001 | 8004 | 139.178.68.207:80 | 1.10.27 | 1425680972 -``` - -Now that the IP and port are known, you can download a full snapshot or an incremental snapshot: - -``` -wget --trust-server-names http://139.178.68.207:80/snapshot.tar.bz2 -wget --trust-server-names http://139.178.68.207:80/incremental-snapshot.tar.bz2 -``` - -Now move those files into your snapshot directory. If you have not specified a snapshot directory, then you should put the files in your ledger directory. - -Once you have a local snapshot, you can restart your validator with the `--no-snapshot-fetch` flag. - -## Regularly Check Account Balances - -It is important that you do not accidentally run out of funds in your identity account, as your node will stop voting. It is also important to note that this account keypair is the most vulnerable of the three keypairs in a vote account because the keypair for the identity account is stored on your validator when running the `solana-validator` software. How much SOL you should store there is up to you. As a best practice, make sure to check the account regularly and refill or deduct from it as needed. To check the account balance do: - -``` -solana balance validator-keypair.json -``` - -> **Note** `solana-watchtower` can monitor for a minimum validator identity balance. See [monitoring best practices](./monitoring.md) for details. - -## Withdrawing From The Vote Account - -As a reminder, your withdrawer's keypair should **_NEVER_** be stored on your server. It should be stored on a hardware wallet, paper wallet, or multisig mitigates the risk of hacking and theft of funds. - -To withdraw your funds from your vote account, you will need to run `solana withdraw-from-vote-account` on a trusted computer. For example, on a trusted computer, you could withdraw all of the funds from your vote account (excluding the rent exempt minimum). The below example assumes you have a separate keypair to store your funds called `person-keypair.json` - -``` -solana withdraw-from-vote-account \ - vote-account-keypair.json \ - person-keypair.json ALL \ - --authorized-withdrawer authorized-withdrawer-keypair.json -``` - -To get more information on the command, use `solana withdraw-from-vote-account --help`. - -For a more detailed explanation of the different keypairs and other related operations refer to [vote account management](../../running-validator/vote-accounts.md). \ No newline at end of file diff --git a/docs/src/validator/blockstore.md b/docs/src/validator/blockstore.md index f4e8a61199..e49e576bf2 100644 --- a/docs/src/validator/blockstore.md +++ b/docs/src/validator/blockstore.md @@ -1,8 +1,9 @@ --- title: Blockstore +sidebar_position: 3 --- -After a block reaches finality, all blocks from that one on down to the genesis block form a linear chain with the familiar name blockchain. Until that point, however, the validator must maintain all potentially valid chains, called _forks_. The process by which forks naturally form as a result of leader rotation is described in [fork generation](../cluster/fork-generation.md). The _blockstore_ data structure described here is how a validator copes with those forks until blocks are finalized. +After a block reaches finality, all blocks from that one on down to the genesis block form a linear chain with the familiar name blockchain. Until that point, however, the validator must maintain all potentially valid chains, called _forks_. The process by which forks naturally form as a result of leader rotation is described in [fork generation](../consensus/fork-generation.md). The _blockstore_ data structure described here is how a validator copes with those forks until blocks are finalized. The blockstore allows a validator to record every shred it observes on the network, in any order, as long as the shred is signed by the expected leader for a given slot. diff --git a/docs/src/developing/plugins/geyser-plugins.md b/docs/src/validator/geyser.md similarity index 100% rename from docs/src/developing/plugins/geyser-plugins.md rename to docs/src/validator/geyser.md diff --git a/docs/src/validator/gossip.md b/docs/src/validator/gossip.md index c1ad139c0e..07a2758fe3 100644 --- a/docs/src/validator/gossip.md +++ b/docs/src/validator/gossip.md @@ -1,36 +1,54 @@ --- title: Gossip Service +sidebar_position: 5 --- -The Gossip Service acts as a gateway to nodes in the [control plane](terminology.md#control-plane). Validators use the service to ensure information is available to all other nodes in a cluster. The service broadcasts information using a [gossip protocol](https://en.wikipedia.org/wiki/Gossip_protocol). +The Gossip Service acts as a gateway to nodes in the +[control plane](https://solana.com/docs/terminology#control-plane). Validators +use the service to ensure information is available to all other nodes in a +cluster. The service broadcasts information using a +[gossip protocol](https://en.wikipedia.org/wiki/Gossip_protocol). ## Gossip Overview -Nodes continuously share signed data objects among themselves in order to manage a cluster. For example, they share their contact information, ledger height, and votes. +Nodes continuously share signed data objects among themselves in order to manage +a cluster. For example, they share their contact information, ledger height, and +votes. -Every tenth of a second, each node sends a "push" message and/or a "pull" message. Push and pull messages may elicit responses, and push messages may be forwarded on to others in the cluster. +Every tenth of a second, each node sends a "push" message and/or a "pull" +message. Push and pull messages may elicit responses, and push messages may be +forwarded on to others in the cluster. -Gossip runs on a well-known UDP/IP port or a port in a well-known range. Once a cluster is bootstrapped, nodes advertise to each other where to find their gossip endpoint (a socket address). +Gossip runs on a well-known UDP/IP port or a port in a well-known range. Once a +cluster is bootstrapped, nodes advertise to each other where to find their +gossip endpoint (a socket address). ## Gossip Records -Records shared over gossip are arbitrary, but signed and versioned (with a timestamp) as needed to make sense to the node receiving them. If a node receives two records from the same source, it updates its own copy with the record with the most recent timestamp. +Records shared over gossip are arbitrary, but signed and versioned (with a +timestamp) as needed to make sense to the node receiving them. If a node +receives two records from the same source, it updates its own copy with the +record with the most recent timestamp. ## Gossip Service Interface ### Push Message -A node sends a push message to tells the cluster it has information to share. Nodes send push messages to `PUSH_FANOUT` push peers. +A node sends a push message to tells the cluster it has information to share. +Nodes send push messages to `PUSH_FANOUT` push peers. Upon receiving a push message, a node examines the message for: -1. Duplication: if the message has been seen before, the node drops the message and may respond with `PushMessagePrune` if forwarded from a low staked node +1. Duplication: if the message has been seen before, the node drops the message + and may respond with `PushMessagePrune` if forwarded from a low staked node 2. New data: if the message is new to the node - - Stores the new information with an updated version in its cluster info and purges any previous older value + - Stores the new information with an updated version in its cluster info and + purges any previous older value - - Stores the message in `pushed_once` (used for detecting duplicates, purged after `PUSH_MSG_TIMEOUT * 5` ms) + - Stores the message in `pushed_once` (used for detecting duplicates, purged + after `PUSH_MSG_TIMEOUT * 5` ms) - Retransmits the messages to its own push peers @@ -38,36 +56,60 @@ Upon receiving a push message, a node examines the message for: ### Push Peers, Prune Message -A nodes selects its push peers at random from the active set of known peers. The node keeps this selection for a relatively long time. When a prune message is received, the node drops the push peer that sent the prune. Prune is an indication that there is another, higher stake weighted path to that node than direct push. +A nodes selects its push peers at random from the active set of known peers. The +node keeps this selection for a relatively long time. When a prune message is +received, the node drops the push peer that sent the prune. Prune is an +indication that there is another, higher stake weighted path to that node than +direct push. -The set of push peers is kept fresh by rotating a new node into the set every `PUSH_MSG_TIMEOUT/2` milliseconds. +The set of push peers is kept fresh by rotating a new node into the set every +`PUSH_MSG_TIMEOUT/2` milliseconds. ### Pull Message -A node sends a pull message to ask the cluster if there is any new information. A pull message is sent to a single peer at random and comprises a Bloom filter that represents things it already has. A node receiving a pull message iterates over its values and constructs a pull response of things that miss the filter and would fit in a message. +A node sends a pull message to ask the cluster if there is any new information. +A pull message is sent to a single peer at random and comprises a Bloom filter +that represents things it already has. A node receiving a pull message iterates +over its values and constructs a pull response of things that miss the filter +and would fit in a message. -A node constructs the pull Bloom filter by iterating over current values and recently purged values. +A node constructs the pull Bloom filter by iterating over current values and +recently purged values. -A node handles items in a pull response the same way it handles new data in a push message. +A node handles items in a pull response the same way it handles new data in a +push message. ## Purging -Nodes retain prior versions of values (those updated by a pull or push) and expired values (those older than `GOSSIP_PULL_CRDS_TIMEOUT_MS`) in `purged_values` (things I recently had). Nodes purge `purged_values` that are older than `5 * GOSSIP_PULL_CRDS_TIMEOUT_MS`. +Nodes retain prior versions of values (those updated by a pull or push) and +expired values (those older than `GOSSIP_PULL_CRDS_TIMEOUT_MS`) in +`purged_values` (things I recently had). Nodes purge `purged_values` that are +older than `5 * GOSSIP_PULL_CRDS_TIMEOUT_MS`. ## Eclipse Attacks -An eclipse attack is an attempt to take over the set of node connections with adversarial endpoints. +An eclipse attack is an attempt to take over the set of node connections with +adversarial endpoints. This is relevant to our implementation in the following ways. -- Pull messages select a random node from the network. An eclipse attack on _pull_ would require an attacker to influence the random selection in such a way that only adversarial nodes are selected for pull. -- Push messages maintain an active set of nodes and select a random fanout for every push message. An eclipse attack on _push_ would influence the active set selection, or the random fanout selection. +- Pull messages select a random node from the network. An eclipse attack on + _pull_ would require an attacker to influence the random selection in such a + way that only adversarial nodes are selected for pull. +- Push messages maintain an active set of nodes and select a random fanout for + every push message. An eclipse attack on _push_ would influence the active set + selection, or the random fanout selection. ### Time and Stake based weights -Weights are calculated based on `time since last picked` and the `natural log` of the `stake weight`. +Weights are calculated based on `time since last picked` and the `natural log` +of the `stake weight`. -Taking the `ln` of the stake weight allows giving all nodes a fairer chance of network coverage in a reasonable amount of time. It helps normalize the large possible `stake weight` differences between nodes. This way a node with low `stake weight`, compared to a node with large `stake weight` will only have to wait a few multiples of ln(`stake`) seconds before it gets picked. +Taking the `ln` of the stake weight allows giving all nodes a fairer chance of +network coverage in a reasonable amount of time. It helps normalize the large +possible `stake weight` differences between nodes. This way a node with low +`stake weight`, compared to a node with large `stake weight` will only have to +wait a few multiples of ln(`stake`) seconds before it gets picked. There is no way for an adversary to influence these parameters. @@ -79,7 +121,8 @@ A node is selected as a pull target based on the weights described above. A prune message can only remove an adversary from a potential connection. -Just like _pull message_, nodes are selected into the active set based on weights. +Just like _pull message_, nodes are selected into the active set based on +weights. ## Notable differences from PlumTree @@ -87,5 +130,9 @@ The active push protocol described here is based on [Plum Tree](https://haslab.uminho.pt/sites/default/files/jop/files/lpr07a.pdf). The main differences are: -- Push messages have a wallclock that is signed by the originator. Once the wallclock expires the message is dropped. A hop limit is difficult to implement in an adversarial setting. -- Lazy Push is not implemented because its not obvious how to prevent an adversary from forging the message fingerprint. A naive approach would allow an adversary to be prioritized for pull based on their input. +- Push messages have a wallclock that is signed by the originator. Once the + wallclock expires the message is dropped. A hop limit is difficult to + implement in an adversarial setting. +- Lazy Push is not implemented because its not obvious how to prevent an + adversary from forging the message fingerprint. A naive approach would allow + an adversary to be prioritized for pull based on their input. diff --git a/docs/src/validator/overview/running-validator-or-rpc-node.md b/docs/src/validator/overview/running-validator-or-rpc-node.md deleted file mode 100644 index 07fff60431..0000000000 --- a/docs/src/validator/overview/running-validator-or-rpc-node.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Consensus Validator or RPC Node? -sidebar_label: Running a Validator or RPC Node? ---- - -Operators who run a [consensus validator](./what-is-a-validator.md) have much different incentives than operators who run an [RPC node](./what-is-an-rpc-node.md). You will have to decide which choice is best for you based on your interests, technical background, and goals. - -## Consensus Validators - -As a validator your primary focus is maintaining the network and making sure that your node is performing optimally so that you can fully participate in the cluster consensus. You will want to attract a delegation of SOL to your validator which will allow your validator the opportunity to produce more blocks and earn rewards. - -Each staked validator earns inflation rewards from [vote credits](../../terminology.md#vote-credit). Vote credits are assigned to validators that vote on [blocks](../../terminology.md#block) produced by the [leader](../../terminology.md#leader). The vote credits are given to all validators that successfully vote on blocks that are added to the blockchain. Additionally, when the validator is the leader, it can earn transaction fees and storage [rent fees](../../developing/programming-model/accounts.md#rent) for each block that it produces that is added to the blockchain. - -Since all votes in Solana happen on the blockchain, a validator incurs a transaction cost for each vote that it makes. These transaction fees amount to approximately 1.0 SOL per day. - -> It is important to make sure your validator always has enough SOL in its identity account to pay for these transactions! - -### Economics of running a consensus validator - -As an operator, it is important to understand how a consensus validator spends and earns sol through the protocol. - -All validators who vote (consensus validators) must pay vote transaction fees for blocks that they agree with. The cost of voting can be up to 1.1 SOL per day. - -A voting validator can earn SOL through 2 methods: - -1. Inflationary rewards paid at the end of an epoch. See [staking rewards](./../../implemented-proposals/staking-rewards.md) -2. Earning 50% of transaction fees for the blocks produced by the validator. See [transaction fee basic economic design](../../transaction_fees.md#basic-economic-design) - -The following links are community provided resources that discuss the economics of running a validator: - -- Michael Hubbard wrote an [article](https://laine-sa.medium.com/solana-staking-rewards-validator-economics-how-does-it-work-6718e4cccc4e) that explains the economics of Solana in more depth for stakers and for validators. -- Congent Crypto has written a [blog post](https://medium.com/@Cogent_Crypto/how-to-become-a-validator-on-solana-9dc4288107b7) that discusses economics and getting started. -- Cogent Crypto also provides a [validator profit calculator](https://cogentcrypto.io/ValidatorProfitCalculator) - -## RPC Nodes - -While RPC operators **do NOT** receive rewards (because the node is not participating in voting), there are different motivations for running an RPC node. - -An RPC operator is providing a service to users who want to interact with the Solana blockchain. Because your primary user is often technical, you will have to be able to answer technical questions about performance of RPC calls. This option may require more understanding of the [core Solana architecture](../../cluster/overview.md). - -If you are operating an RPC node as a business, your job will also involve scaling your system to meet the demands of the users. For example, some RPC providers create dedicated servers for projects that require a high volume of requests to the node. Someone with a background in development operations or software engineering will be a very important part of your team. You will need a strong understanding of the Solana architecture and the [RPC API](../../api/http.md). - -Alternatively, you may be a development team that would like to run their own infrastructure. In this case, the RPC infrastructure could be a part of your production stack. A development team could use the [Geyser plugin](../../developing/plugins/geyser-plugins.md), for example, to get real time access to information about accounts or blocks in the cluster. \ No newline at end of file diff --git a/docs/src/validator/runtime.md b/docs/src/validator/runtime.md index f02030b13e..48fa7f041b 100644 --- a/docs/src/validator/runtime.md +++ b/docs/src/validator/runtime.md @@ -1,9 +1,8 @@ --- -title: The Runtime +title: Runtime +sidebar_position: 6 --- -## The Runtime - The runtime is a concurrent transaction processor. Transactions specify their data dependencies upfront and dynamic memory allocation is explicit. By separating program code from the state it operates on, the runtime is able to choreograph concurrent access. Transactions accessing only read-only accounts are executed in parallel whereas transactions accessing writable accounts are serialized. The runtime interacts with the program through an entrypoint with a well-defined interface. The data stored in an account is an opaque type, an array of bytes. The program has full control over its contents. The transaction structure specifies a list of public keys and signatures for those keys and a sequential list of instructions that will operate over the states associated with the account keys. For the transaction to be committed all the instructions must execute successfully; if any abort the whole transaction fails to commit. diff --git a/docs/src/validator/tpu.md b/docs/src/validator/tpu.md index 4445d8d698..a3271add28 100644 --- a/docs/src/validator/tpu.md +++ b/docs/src/validator/tpu.md @@ -1,5 +1,7 @@ --- -title: TPU +title: Transaction Processing Unit +sidebar_label: TPU +sidebar_position: 2 --- TPU (Transaction Processing Unit) is the logic of the validator diff --git a/docs/src/validator/tvu.md b/docs/src/validator/tvu.md index 04657ab5e9..e3ac7776f0 100644 --- a/docs/src/validator/tvu.md +++ b/docs/src/validator/tvu.md @@ -1,5 +1,7 @@ --- -title: TVU +title: Transaction Validation Unit +sidebar_label: TVU +sidebar_position: 3 --- TVU (Transaction Validation Unit) is the logic of the validator diff --git a/docs/src/wallet-guide.md b/docs/src/wallet-guide.md deleted file mode 100644 index f6a380b51d..0000000000 --- a/docs/src/wallet-guide.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Solana Wallet Guide ---- - -This document describes the different wallet options that are available to users -of Solana who want to be able to send, receive and interact with -SOL tokens on the Solana blockchain. - -## What is a Wallet? - -A crypto wallet is a device or application that stores a collection of keys and -can be used to send, receive, -and track ownership of cryptocurrencies. Wallets can take many forms. -A wallet might be a directory or file in your computer's file system, -a piece of paper, or a specialized device called a _hardware wallet_. -There are also various smartphone apps and computer programs -that provide a user-friendly way to create and manage wallets. - -A _keypair_ is a securely generated _private key_ and its -cryptographically-derived _public key_. A private key and its corresponding -public key are together known as a _keypair_. -A wallet contains a collection of one or more keypairs and provides some means -to interact with them. - -The _public key_ (commonly shortened to _pubkey_) is known as the wallet's -_receiving address_ or simply its _address_. The wallet address **may be shared -and displayed freely**. When another party is going to send some amount of -cryptocurrency to a wallet, they need to know the wallet's receiving address. -Depending on a blockchain's implementation, the address can also be used to view -certain information about a wallet, such as viewing the balance, -but has no ability to change anything about the wallet or withdraw any tokens. - -The _private key_ is required to digitally sign any transactions to send -cryptocurrencies to another address or to make any changes to the wallet. -The private key **must never be shared**. If someone gains access to the -private key to a wallet, they can withdraw all the tokens it contains. -If the private key for a wallet is lost, any tokens that have been sent -to that wallet's address are **permanently lost**. - -Different wallet solutions offer different approaches to keypair security, -interacting with the keypair, and signing transactions to use/spend the tokens. -Some are easier to use than others. -Some store and back up private keys more securely. -Solana supports multiple types of wallets so you can choose the right balance -of security and convenience. - -**If you want to be able to receive SOL tokens on the Solana blockchain, -you first will need to create a wallet.** - -## Supported Wallets - -Several browser and mobile app based wallets support Solana. Find the right one -for you on the [Solana Ecosystem](https://solana.com/ecosystem/explore?categories=wallet) -page. - -For advanced users or developers, the [command-line wallets](wallet-guide/cli.md) -may be more appropriate, as new features on the Solana blockchain will always be -supported on the command line first before being integrated into third-party -solutions. diff --git a/docs/src/wallet-guide/support.md b/docs/src/wallet-guide/support.md deleted file mode 100644 index 84df5e8667..0000000000 --- a/docs/src/wallet-guide/support.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Support / Troubleshooting ---- - -If you have questions or are having trouble setting up or using your wallet -of choice, please make sure you've read through all the relevant pages in our -[Wallet Guide](paper-wallet.md). The Solana team is working hard to support new -features on popular wallets, and we do our best to keep our documents up to date -with the latest available features. - -If you have questions after reading the docs, feel free to reach out to us on -our [Telegram](https://t.me/solana). - -For **technical support**, please ask a question on [StackOverflow](https://stackoverflow.com/questions/tagged/solana) and tag your questions with `solana`. diff --git a/docs/src/validator/overview/what-is-a-validator.md b/docs/src/what-is-a-validator.md similarity index 97% rename from docs/src/validator/overview/what-is-a-validator.md rename to docs/src/what-is-a-validator.md index f2a34d2f9c..c5e2b1b9d8 100644 --- a/docs/src/validator/overview/what-is-a-validator.md +++ b/docs/src/what-is-a-validator.md @@ -36,4 +36,4 @@ Understanding how PoH works is not necessary to run a good validator, but a very As a validator, you are helping to secure the network by producing and voting on blocks and to improve decentralization by running an independent node. You have the right to participate in discussions of changes on the network. You are also assuming a responsibility to keep your system running properly, to make sure your system is secure, and to keep it up to date with the latest software. As more individuals stake their tokens to your validator, you can reward their trust by running a high performing and reliable validator. Hopefully, your validator is performing well a majority of the time, but you should also have systems in place to respond to an outage at any time of the day. If your validator is not responding late at night, someone (either you or other team members) need to be available to investigate and fix the issues. -Running a validator is a [technical and important task](./validator-prerequisites.md), but it can also be very rewarding. Good luck and welcome to the community. \ No newline at end of file +Running a validator is a [technical and important task](./operations/prerequisites.md), but it can also be very rewarding. Good luck and welcome to the community. \ No newline at end of file diff --git a/docs/src/validator/overview/what-is-an-rpc-node.md b/docs/src/what-is-an-rpc-node.md similarity index 71% rename from docs/src/validator/overview/what-is-an-rpc-node.md rename to docs/src/what-is-an-rpc-node.md index 59cf2c8b42..6bf75915a8 100644 --- a/docs/src/validator/overview/what-is-an-rpc-node.md +++ b/docs/src/what-is-an-rpc-node.md @@ -2,11 +2,11 @@ title: What is an RPC Node? --- -An RPC (Remote Procedure Call) node runs the same software as a [validator](../overview/what-is-a-validator.md), but it does not participate in the consensus process. Technically you could run the RPC software and also allow your node to vote as a consensus node, but it is strongly discouraged because your node will not be performant enough to do either task well. +An RPC (Remote Procedure Call) node runs the same software as a [validator](./what-is-a-validator.md), but it does not participate in the consensus process. Technically you could run the RPC software and also allow your node to vote as a consensus node, but it is strongly discouraged because your node will not be performant enough to do either task well. A node that runs RPC has a much different purpose in the cluster. An RPC node responds to requests about the blockchain and also allows users of the RPC node to submit new transactions to be included in blocks. For example, a website might request to transfer tokens from wallet A to wallet B (given wallet A's permission). That website would have to use wallet A to sign a transaction and then send it to an RPC node to be submitted to the leader. So you could think of running an RPC node as a similar engineering task to providing an api for others to use. The users of the RPC node are often developers, so this option may require a more technical understanding of Solana. To better understand RPC node operations, you'll want to become familiar with the different RPC calls. -You can find the RPC API [here](../../api/http.md). \ No newline at end of file +You can find the [RPC API here](https://solana.com/docs/rpc/http). \ No newline at end of file diff --git a/docs/static/img/quickstarts/solana-get-started-build-and-deploy.png b/docs/static/img/quickstarts/solana-get-started-build-and-deploy.png deleted file mode 100644 index 59bb3ef527..0000000000 Binary files a/docs/static/img/quickstarts/solana-get-started-build-and-deploy.png and /dev/null differ diff --git a/docs/static/img/quickstarts/solana-get-started-import-on-playground.png b/docs/static/img/quickstarts/solana-get-started-import-on-playground.png deleted file mode 100644 index cd90b00cb2..0000000000 Binary files a/docs/static/img/quickstarts/solana-get-started-import-on-playground.png and /dev/null differ diff --git a/docs/static/img/quickstarts/solana-get-started-successful-build.png b/docs/static/img/quickstarts/solana-get-started-successful-build.png deleted file mode 100644 index 82b0a5df05..0000000000 Binary files a/docs/static/img/quickstarts/solana-get-started-successful-build.png and /dev/null differ diff --git a/docs/static/img/quickstarts/solana-overview-client-program.png b/docs/static/img/quickstarts/solana-overview-client-program.png deleted file mode 100644 index 42b80cee54..0000000000 Binary files a/docs/static/img/quickstarts/solana-overview-client-program.png and /dev/null differ