diff --git a/.buildkite/hooks/pre-command b/.buildkite/hooks/pre-command
index 025b228f857..4c798a83d36 100644
--- a/.buildkite/hooks/pre-command
+++ b/.buildkite/hooks/pre-command
@@ -28,5 +28,11 @@ fi
export SBF_TOOLS_VERSION
-SCCACHE_S3_KEY_PREFIX="${rust_stable}_${rust_nightly}_${SBF_TOOLS_VERSION}"
+SCCACHE_KEY_PREFIX="${rust_stable}_${rust_nightly}_${SBF_TOOLS_VERSION}"
+export SCCACHE_KEY_PREFIX
+
+SCCACHE_S3_KEY_PREFIX="$SCCACHE_KEY_PREFIX"
export SCCACHE_S3_KEY_PREFIX
+
+SCCACHE_GCS_KEY_PREFIX="$SCCACHE_KEY_PREFIX"
+export SCCACHE_GCS_KEY_PREFIX
diff --git a/.github/scripts/cargo-clippy-before-script.sh b/.github/scripts/cargo-clippy-before-script.sh
new file mode 100755
index 00000000000..b9426203aa6
--- /dev/null
+++ b/.github/scripts/cargo-clippy-before-script.sh
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+
+set -e
+
+os_name="$1"
+
+case "$os_name" in
+"Windows")
+ ;;
+"macOS")
+ brew install protobuf
+ ;;
+"Linux") ;;
+*)
+ echo "Unknown Operating System"
+ ;;
+esac
diff --git a/.github/scripts/downstream-project-spl-common.sh b/.github/scripts/downstream-project-spl-common.sh
index c6dcfaca007..47237e71c9c 100644
--- a/.github/scripts/downstream-project-spl-common.sh
+++ b/.github/scripts/downstream-project-spl-common.sh
@@ -8,7 +8,7 @@ source "$here"/../../ci/downstream-projects/common.sh
set -x
rm -rf spl
-git clone https://github.com/solana-labs/solana-program-library.git spl
+git clone https://github.com/solana-labs/solana-program-library.git spl -b v1.17
# copy toolchain file to use solana's rust version
cp "$SOLANA_DIR"/rust-toolchain.toml spl/
@@ -22,3 +22,5 @@ if semverGT "$project_used_solana_version" "$SOLANA_VER"; then
fi
./patch.crates-io.sh "$SOLANA_DIR"
+# anza migration stopgap. can be removed when agave is fully recommended for public usage.
+sed -i 's/solana-geyser-plugin-interface/agave-geyser-plugin-interface/g' ./Cargo.toml
diff --git a/.github/workflows/cargo.yml b/.github/workflows/cargo.yml
new file mode 100644
index 00000000000..d0bad722e0d
--- /dev/null
+++ b/.github/workflows/cargo.yml
@@ -0,0 +1,71 @@
+name: Cargo
+
+on:
+ push:
+ branches:
+ - master
+ - v[0-9]+.[0-9]+
+ pull_request:
+ branches:
+ - master
+ - v[0-9]+.[0-9]+
+ paths:
+ - "**.rs"
+ - "**/Cargo.toml"
+ - "**/Cargo.lock"
+ - ".github/scripts/cargo-clippy-before-script.sh"
+ - ".github/workflows/cargo.yml"
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
+env:
+ SHELL: /bin/bash
+ SCCACHE_GHA_ENABLED: "true"
+ RUSTC_WRAPPER: "sccache"
+
+jobs:
+ clippy-stable:
+ strategy:
+ matrix:
+ os:
+ - macos-latest
+ runs-on: ${{ matrix.os }}
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: mozilla-actions/sccache-action@v0.0.3
+ with:
+ version: "v0.5.4"
+
+ - shell: bash
+ run: .github/scripts/cargo-clippy-before-script.sh ${{ runner.os }}
+
+ - shell: bash
+ run: |
+ source ci/rust-version.sh stable
+ rustup component add clippy --toolchain "$rust_stable"
+ scripts/cargo-clippy-stable.sh
+
+ clippy-nightly:
+ strategy:
+ matrix:
+ os:
+ - macos-latest
+ runs-on: ${{ matrix.os }}
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: mozilla-actions/sccache-action@v0.0.3
+ with:
+ version: "v0.5.4"
+
+ - shell: bash
+ run: .github/scripts/cargo-clippy-before-script.sh ${{ runner.os }}
+
+ - shell: bash
+ run: |
+ source ci/rust-version.sh nightly
+ rustup component add clippy --toolchain "$rust_nightly"
+ scripts/cargo-clippy-nightly.sh
diff --git a/.github/workflows/downstream-project-spl.yml b/.github/workflows/downstream-project-spl.yml
index f0ecfb20acc..6afd398f43a 100644
--- a/.github/workflows/downstream-project-spl.yml
+++ b/.github/workflows/downstream-project-spl.yml
@@ -43,6 +43,8 @@ jobs:
.github/scripts/purge-ubuntu-runner.sh
- uses: mozilla-actions/sccache-action@v0.0.3
+ with:
+ version: "v0.5.4"
- shell: bash
run: |
@@ -90,6 +92,8 @@ jobs:
.github/scripts/purge-ubuntu-runner.sh
- uses: mozilla-actions/sccache-action@v0.0.3
+ with:
+ version: "v0.5.4"
- shell: bash
run: |
@@ -139,6 +143,8 @@ jobs:
.github/scripts/purge-ubuntu-runner.sh
- uses: mozilla-actions/sccache-action@v0.0.3
+ with:
+ version: "v0.5.4"
- shell: bash
run: |
diff --git a/.github/workflows/release-artifacts-auto.yml b/.github/workflows/release-artifacts-auto.yml
index a8309cdffc8..0cdd176e043 100644
--- a/.github/workflows/release-artifacts-auto.yml
+++ b/.github/workflows/release-artifacts-auto.yml
@@ -14,14 +14,12 @@ concurrency:
jobs:
release-artifacts:
- if: github.repository == 'solana-labs/solana'
+ if: github.repository == 'anza-xyz/agave'
uses: ./.github/workflows/release-artifacts.yml
with:
commit: ${{ github.sha }}
secrets:
- AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
- AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
+ GCS_RELEASE_BUCKET_WRITER_CREDIENTIAL: ${{ secrets.GCS_RELEASE_BUCKET_WRITER_CREDIENTIAL }}
error_reporting:
needs:
diff --git a/.github/workflows/release-artifacts-manually.yml b/.github/workflows/release-artifacts-manually.yml
index 35de72922c3..fe5c1b03b63 100644
--- a/.github/workflows/release-artifacts-manually.yml
+++ b/.github/workflows/release-artifacts-manually.yml
@@ -14,6 +14,4 @@ jobs:
with:
commit: ${{ github.event.inputs.commit }}
secrets:
- AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
- AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
+ GCS_RELEASE_BUCKET_WRITER_CREDIENTIAL: ${{ secrets.GCS_RELEASE_BUCKET_WRITER_CREDIENTIAL }}
diff --git a/.github/workflows/release-artifacts.yml b/.github/workflows/release-artifacts.yml
index 3e5ab89fe33..08d7e56fdab 100644
--- a/.github/workflows/release-artifacts.yml
+++ b/.github/workflows/release-artifacts.yml
@@ -7,11 +7,7 @@ on:
required: false
type: string
secrets:
- AWS_ACCESS_KEY_ID:
- required: true
- AWS_SECRET_ACCESS_KEY:
- required: true
- AWS_S3_BUCKET:
+ GCS_RELEASE_BUCKET_WRITER_CREDIENTIAL:
required: true
jobs:
@@ -47,7 +43,7 @@ jobs:
id: build
shell: bash
run: |
- choco install openssl
+ choco install openssl --version=3.1.1
if [[ -d "C:\Program Files\OpenSSL" ]]; then
echo "OPENSSL_DIR: C:\Program Files\OpenSSL"
export OPENSSL_DIR="C:\Program Files\OpenSSL"
@@ -71,19 +67,19 @@ jobs:
shell: bash
run: |
FOLDER_NAME=${{ steps.build.outputs.tag || steps.build.outputs.channel }}
- mkdir -p "github-action-s3-upload/$FOLDER_NAME"
- cp -v "solana-release-x86_64-pc-windows-msvc.tar.bz2" "github-action-s3-upload/$FOLDER_NAME/"
- cp -v "solana-release-x86_64-pc-windows-msvc.yml" "github-action-s3-upload/$FOLDER_NAME/"
- cp -v "solana-install-init-x86_64-pc-windows-msvc"* "github-action-s3-upload/$FOLDER_NAME"
+ mkdir -p "windows-release/$FOLDER_NAME"
+ cp -v "solana-release-x86_64-pc-windows-msvc.tar.bz2" "windows-release/$FOLDER_NAME/"
+ cp -v "solana-release-x86_64-pc-windows-msvc.yml" "windows-release/$FOLDER_NAME/"
+ cp -v "agave-install-init-x86_64-pc-windows-msvc"* "windows-release/$FOLDER_NAME"
- name: Upload Artifacts
if: ${{ steps.build.outputs.channel != '' || steps.build.outputs.tag != '' }}
uses: actions/upload-artifact@v3
with:
name: windows-artifact
- path: github-action-s3-upload/
+ path: windows-release/
- windows-s3-upload:
+ windows-gcs-upload:
if: ${{ needs.windows-build.outputs.channel != '' || needs.windows-build.outputs.tag != '' }}
needs: [windows-build]
runs-on: ubuntu-20.04
@@ -92,18 +88,16 @@ jobs:
uses: actions/download-artifact@v3
with:
name: windows-artifact
- path: ./github-action-s3-upload
+ path: ./windows-release
- - name: Upload
- uses: jakejarvis/s3-sync-action@master
+ - name: Setup crediential
+ uses: "google-github-actions/auth@v2"
with:
- args: --acl public-read --follow-symlinks
- env:
- AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
- AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
- AWS_REGION: "us-west-1"
- SOURCE_DIR: "github-action-s3-upload"
+ credentials_json: "${{ secrets.GCS_RELEASE_BUCKET_WRITER_CREDIENTIAL }}"
+
+ - name: Upload files to GCS
+ run: |
+ gcloud storage cp --recursive windows-release/* gs://anza-release/
windows-gh-release:
if: ${{ needs.windows-build.outputs.tag != '' }}
@@ -114,7 +108,7 @@ jobs:
uses: actions/download-artifact@v3
with:
name: windows-artifact
- path: ./github-action-s3-upload
+ path: ./windows-release/
- name: Release
uses: softprops/action-gh-release@v1
@@ -122,4 +116,4 @@ jobs:
tag_name: ${{ needs.windows-build.outputs.tag }}
draft: true
files: |
- github-action-s3-upload/${{ needs.windows-build.outputs.tag }}/*
+ windows-release/${{ needs.windows-build.outputs.tag }}/*
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 00000000000..78a6d029d4c
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,89 @@
+name: Release
+
+on:
+ push:
+ tags:
+ - "*"
+
+jobs:
+ trigger-buildkite-pipeline:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Trigger a Buildkite Build
+ uses: "buildkite/trigger-pipeline-action@v2.0.0"
+ with:
+ buildkite_api_access_token: ${{ secrets.TRIGGER_BK_BUILD_TOKEN }}
+ pipeline: "anza/agave-secondary"
+ branch: "${{ github.ref_name }}"
+ build_env_vars: '{"TRIGGERED_BUILDKITE_TAG": "${{ github.ref_name }}"}'
+ commit: "HEAD"
+ message: ":github: Triggered from a GitHub Action"
+
+ draft-release:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Create Release
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ github.rest.repos.createRelease({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ tag_name: '${{ github.ref_name }}',
+ name: 'Release ${{ github.ref_name }}',
+ body: '🚧',
+ draft: false,
+ prerelease: true
+ })
+
+ version-bump:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Parse Info
+ id: parse_info
+ run: |
+ # get the next version
+ version=${{ github.ref_name }}
+ major=$(echo $version | cut -d'.' -f1)
+ minor=$(echo $version | cut -d'.' -f2)
+ patch=$(echo $version | cut -d'.' -f3)
+ next_version=$major.$minor.$((patch+1))
+ : "${next_version:?}"
+
+ # get the traget branch
+ target_branch=$major.$minor
+ : "${target_branch:?}"
+
+ echo "next_version=$next_version" | tee -a $GITHUB_OUTPUT
+ echo "target_branch=$target_branch" | tee -a $GITHUB_OUTPUT
+
+ - name: Create branch and make changes
+ run: |
+ next_version=${{ steps.parse_info.outputs.next_version }}
+
+ git checkout -b version-bump-$next_version
+ ./scripts/increment-cargo-version.sh patch
+
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
+ git config user.name "github-actions[bot]"
+ git commit -am "Bump version to $next_version"
+ git push origin version-bump-$next_version
+
+ - name: Create PR
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ github.rest.pulls.create({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ title: 'Bump version to ${{ steps.parse_info.outputs.next_version }}',
+ head: 'version-bump-${{ steps.parse_info.outputs.next_version }}',
+ base: '${{ steps.parse_info.outputs.target_branch }}'
+ })
diff --git a/.mergify.yml b/.mergify.yml
index 1fca661dddd..fe910363019 100644
--- a/.mergify.yml
+++ b/.mergify.yml
@@ -33,7 +33,7 @@ pull_request_rules:
actions:
request_reviews:
teams:
- - "@solana-labs/community-pr-subscribers"
+ - "@anza-xyz/community-pr-subscribers"
- name: label changes from monorepo-triage
conditions:
- author≠@core-contributors
@@ -50,7 +50,7 @@ pull_request_rules:
- name: automatic merge (squash) on CI success
conditions:
- and:
- - status-success=buildkite/solana
+ - status-success=buildkite/agave
- status-success=ci-gate
- label=automerge
- label!=no-automerge
@@ -80,7 +80,7 @@ pull_request_rules:
actions:
backport:
assignees: &BackportAssignee
- - "{{ merged_by|replace('mergify[bot]', label|select('equalto', 'community')|first|default(author)|replace('community', '@solana-labs/community-pr-subscribers')) }}"
+ - "{{ merged_by|replace('mergify[bot]', label|select('equalto', 'community')|first|default(author)|replace('community', '@anza-xyz/community-pr-subscribers')) }}"
title: "{{ destination_branch }}: {{ title }} (backport of #{{ number }})"
ignore_conflicts: true
labels:
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index c2dd13e3255..00000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,94 +0,0 @@
-branches:
- only:
- - master
- - /^v\d+\.\d+/
-
-notifications:
- email: false
- slack:
- on_success: change
- if: NOT type = pull_request
- secure: F4IjOE05MyaMOdPRL+r8qhs7jBvv4yDM3RmFKE1zNXnfUOqV4X38oQM1EI+YVsgpMQLj/pxnEB7wcTE4Bf86N6moLssEULCpvAuMVoXj4QbWdomLX+01WbFa6fLVeNQIg45NHrz2XzVBhoKOrMNnl+QI5mbR2AlS5oqsudHsXDnyLzZtd4Y5SDMdYG1zVWM01+oNNjgNfjcCGmOE/K0CnOMl6GPi3X9C34tJ19P2XT7MTDsz1/IfEF7fro2Q8DHEYL9dchJMoisXSkem5z7IDQkGzXsWdWT4NnndUvmd1MlTCE9qgoXDqRf95Qh8sB1Dz08HtvgfaosP2XjtNTfDI9BBYS15Ibw9y7PchAJE1luteNjF35EOy6OgmCLw/YpnweqfuNViBZz+yOPWXVC0kxnPIXKZ1wyH9ibeH6E4hr7a8o9SV/6SiWIlbYF+IR9jPXyTCLP/cc3sYljPWxDnhWFwFdRVIi3PbVAhVu7uWtVUO17Oc9gtGPgs/GrhOMkJfwQPXaudRJDpVZowxTX4x9kefNotlMAMRgq+Drbmgt4eEBiCNp0ITWgh17BiE1U09WS3myuduhoct85+FoVeaUkp1sxzHVtGsNQH0hcz7WcpZyOM+AwistJA/qzeEDQao5zi1eKWPbO2xAhi2rV1bDH6bPf/4lDBwLRqSiwvlWU=
-
-os: linux
-dist: bionic
-language: minimal
-
-jobs:
- include:
- - &release-artifacts
- if: type IN (api, cron) OR tag IS present
- name: "macOS release artifacts"
- os: osx
- osx_image: xcode12
- language: rust
- rust:
- - stable
- install:
- - source ci/rust-version.sh
- - PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
- - readlink -f .
- - brew install gnu-tar
- - PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"
- - tar --version
- script:
- - source ci/env.sh
- - rustup set profile default
- - ci/publish-tarball.sh
- deploy:
- - provider: s3
- access_key_id: $AWS_ACCESS_KEY_ID
- secret_access_key: $AWS_SECRET_ACCESS_KEY
- bucket: release.solana.com
- region: us-west-1
- skip_cleanup: true
- acl: public_read
- local_dir: travis-s3-upload
- on:
- all_branches: true
- - provider: releases
- token: $GITHUB_TOKEN
- skip_cleanup: true
- file_glob: true
- file: travis-release-upload/*
- on:
- tags: true
- - <<: *release-artifacts
- name: "Windows release artifacts"
- os: windows
- install:
- - choco install openssl
- - export OPENSSL_DIR="C:\Program Files\OpenSSL-Win64"
- - source ci/rust-version.sh
- - PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
- - readlink -f .
- # Linux release artifacts are still built by ci/buildkite-secondary.yml
- #- <<: *release-artifacts
- # name: "Linux release artifacts"
- # os: linux
- # before_install:
- # - sudo apt-get install libssl-dev libudev-dev
-
- # docs pull request
- - name: "docs"
- if: type IN (push, pull_request) OR tag IS present
- language: node_js
- node_js:
- - "lts/*"
-
- services:
- - docker
-
- cache:
- directories:
- - ~/.npm
-
- before_install:
- - source ci/env.sh
- - .travis/channel_restriction.sh edge beta || travis_terminate 0
- - .travis/affects.sh docs/ .travis || travis_terminate 0
- - cd docs/
- - source .travis/before_install.sh
-
- script:
- - source .travis/script.sh
diff --git a/CHANGELOG.md b/CHANGELOG.md
index df54c187651..a5c7410ba55 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,17 +4,22 @@ All notable changes to this project will be documented in this file.
Please follow the [guidance](#adding-to-this-changelog) at the bottom of this file when making changes
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
-and follows a [Backwards Compatability Policy](https://docs.solana.com/developing/backwards-compatibility)
+and follows a [Backwards Compatibility Policy](https://docs.solana.com/developing/backwards-compatibility)
-Release channels have their own copy of this changelog:
-* [edge - v1.17](#edge-channel)
-* [beta - v1.16](https://github.com/solana-labs/solana/blob/v1.16/CHANGELOG.md)
-* [stable - v1.14](https://github.com/solana-labs/solana/blob/v1.14/CHANGELOG.md)
+## [1.17.3] - Unreleased
+* Changes
+* Upgrade Notes
+
+## [1.17.2]
+* minor bug fixes and improvements
+
+## [1.17.1]
+* minor bug fixes and improvements
-
-## [1.17.0] - Unreleased
+## [1.17.0]
* Changes
* Added a changelog.
+ * Added `--use-snapshot-archives-at-startup` for faster validator restarts
* Upgrade Notes
## Adding to this Changelog
diff --git a/Cargo.lock b/Cargo.lock
index c892fd686a6..468693b0a7a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -63,6 +63,183 @@ dependencies = [
"zeroize",
]
+[[package]]
+name = "agave-geyser-plugin-interface"
+version = "1.17.30"
+dependencies = [
+ "log",
+ "solana-sdk",
+ "solana-transaction-status",
+ "thiserror",
+]
+
+[[package]]
+name = "agave-install"
+version = "1.17.30"
+dependencies = [
+ "atty",
+ "bincode",
+ "bzip2",
+ "chrono",
+ "clap 2.33.3",
+ "console",
+ "crossbeam-channel",
+ "ctrlc",
+ "dirs-next",
+ "indicatif",
+ "lazy_static",
+ "nix 0.26.4",
+ "reqwest",
+ "scopeguard",
+ "semver 1.0.20",
+ "serde",
+ "serde_yaml 0.8.26",
+ "serde_yaml 0.9.25",
+ "solana-clap-utils",
+ "solana-config-program",
+ "solana-logger",
+ "solana-rpc-client",
+ "solana-sdk",
+ "solana-version",
+ "tar",
+ "tempfile",
+ "url 2.4.1",
+ "winapi 0.3.9",
+ "winreg",
+]
+
+[[package]]
+name = "agave-ledger-tool"
+version = "1.17.30"
+dependencies = [
+ "assert_cmd",
+ "bs58",
+ "bytecount",
+ "chrono",
+ "clap 2.33.3",
+ "crossbeam-channel",
+ "csv",
+ "dashmap 4.0.2",
+ "futures 0.3.28",
+ "histogram",
+ "itertools",
+ "log",
+ "num_cpus",
+ "regex",
+ "serde",
+ "serde_json",
+ "signal-hook",
+ "solana-account-decoder",
+ "solana-accounts-db",
+ "solana-bpf-loader-program",
+ "solana-clap-utils",
+ "solana-cli-output",
+ "solana-core",
+ "solana-cost-model",
+ "solana-entry",
+ "solana-geyser-plugin-manager",
+ "solana-gossip",
+ "solana-ledger",
+ "solana-logger",
+ "solana-measure",
+ "solana-program-runtime",
+ "solana-rpc",
+ "solana-runtime",
+ "solana-sdk",
+ "solana-stake-program",
+ "solana-storage-bigtable",
+ "solana-streamer",
+ "solana-transaction-status",
+ "solana-version",
+ "solana-vote-program",
+ "solana_rbpf",
+ "tikv-jemallocator",
+ "tokio",
+]
+
+[[package]]
+name = "agave-validator"
+version = "1.17.30"
+dependencies = [
+ "agave-geyser-plugin-interface",
+ "chrono",
+ "clap 2.33.3",
+ "console",
+ "core_affinity",
+ "crossbeam-channel",
+ "fd-lock",
+ "indicatif",
+ "itertools",
+ "jsonrpc-core",
+ "jsonrpc-core-client",
+ "jsonrpc-derive",
+ "jsonrpc-ipc-server",
+ "jsonrpc-server-utils",
+ "lazy_static",
+ "libc",
+ "libloading",
+ "log",
+ "num_cpus",
+ "rand 0.8.5",
+ "rayon",
+ "serde",
+ "serde_json",
+ "serde_yaml 0.9.25",
+ "signal-hook",
+ "solana-account-decoder",
+ "solana-accounts-db",
+ "solana-clap-utils",
+ "solana-cli-config",
+ "solana-core",
+ "solana-download-utils",
+ "solana-entry",
+ "solana-faucet",
+ "solana-genesis-utils",
+ "solana-geyser-plugin-manager",
+ "solana-gossip",
+ "solana-ledger",
+ "solana-logger",
+ "solana-metrics",
+ "solana-net-utils",
+ "solana-perf",
+ "solana-poh",
+ "solana-rpc",
+ "solana-rpc-client",
+ "solana-rpc-client-api",
+ "solana-runtime",
+ "solana-sdk",
+ "solana-send-transaction-service",
+ "solana-storage-bigtable",
+ "solana-streamer",
+ "solana-test-validator",
+ "solana-tpu-client",
+ "solana-version",
+ "solana-vote-program",
+ "spl-token-2022",
+ "symlink",
+ "thiserror",
+ "tikv-jemallocator",
+]
+
+[[package]]
+name = "agave-watchtower"
+version = "1.17.30"
+dependencies = [
+ "clap 2.33.3",
+ "humantime",
+ "log",
+ "solana-clap-utils",
+ "solana-cli-config",
+ "solana-cli-output",
+ "solana-logger",
+ "solana-metrics",
+ "solana-notifier",
+ "solana-rpc-client",
+ "solana-rpc-client-api",
+ "solana-sdk",
+ "solana-version",
+]
+
[[package]]
name = "ahash"
version = "0.7.6"
@@ -76,14 +253,15 @@ dependencies = [
[[package]]
name = "ahash"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
+checksum = "cd7d5a2cecb58716e47d67d5703a249964b14c7be1ec3cad3affc295b2d1c35d"
dependencies = [
"cfg-if 1.0.0",
"getrandom 0.2.10",
"once_cell",
"version_check",
+ "zerocopy",
]
[[package]]
@@ -430,13 +608,13 @@ dependencies = [
[[package]]
name = "async-trait"
-version = "0.1.73"
+version = "0.1.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
+checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -590,7 +768,7 @@ dependencies = [
"regex",
"rustc-hash",
"shlex",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -709,7 +887,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b"
dependencies = [
"borsh-derive 0.10.3",
- "hashbrown 0.13.2",
+ "hashbrown 0.12.3",
]
[[package]]
@@ -864,9 +1042,9 @@ dependencies = [
[[package]]
name = "bytecount"
-version = "0.6.3"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c"
+checksum = "ad152d03a2c813c80bb94fedbf3a3f02b28f793e39e7c214c8a0bcc196343de7"
[[package]]
name = "bytemuck"
@@ -890,9 +1068,9 @@ dependencies = [
[[package]]
name = "byteorder"
-version = "1.4.3"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
@@ -963,7 +1141,7 @@ checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a"
dependencies = [
"camino",
"cargo-platform",
- "semver 1.0.19",
+ "semver 1.0.20",
"serde",
"serde_json",
"thiserror",
@@ -1228,18 +1406,18 @@ checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
[[package]]
name = "const_format"
-version = "0.2.31"
+version = "0.2.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c990efc7a285731f9a4378d81aff2f0e85a2c8781a05ef0f8baa8dac54d0ff48"
+checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673"
dependencies = [
"const_format_proc_macros",
]
[[package]]
name = "const_format_proc_macros"
-version = "0.2.31"
+version = "0.2.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e026b6ce194a874cb9cf32cd5772d1ef9767cc8fcb5765948d74f37a9d8b2bf6"
+checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500"
dependencies = [
"proc-macro2",
"quote",
@@ -1423,9 +1601,9 @@ dependencies = [
[[package]]
name = "csv"
-version = "1.2.2"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086"
+checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe"
dependencies = [
"csv-core",
"itoa",
@@ -1435,9 +1613,9 @@ dependencies = [
[[package]]
name = "csv-core"
-version = "0.1.10"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
+checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70"
dependencies = [
"memchr",
]
@@ -1496,7 +1674,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim 0.10.0",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -1507,7 +1685,7 @@ checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a"
dependencies = [
"darling_core",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -1523,13 +1701,15 @@ dependencies = [
[[package]]
name = "dashmap"
-version = "5.2.0"
+version = "5.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c8858831f7781322e539ea39e72449c46b059638250c14344fec8d0aa6e539c"
+checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
dependencies = [
"cfg-if 1.0.0",
- "num_cpus",
- "parking_lot 0.12.1",
+ "hashbrown 0.14.1",
+ "lock_api",
+ "once_cell",
+ "parking_lot_core 0.9.8",
]
[[package]]
@@ -1699,7 +1879,7 @@ checksum = "a6cbae11b3de8fce2a456e8ea3dada226b35fe791f0dc1d360c0941f0bb681f3"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -1746,7 +1926,7 @@ dependencies = [
"derivation-path",
"ed25519-dalek",
"hmac 0.12.1",
- "sha2 0.10.7",
+ "sha2 0.10.8",
]
[[package]]
@@ -1799,7 +1979,7 @@ checksum = "eecf8589574ce9b895052fa12d69af7a233f99e6107f5cb8dd1044f2a17bfdcb"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -1946,9 +2126,9 @@ checksum = "398ea4fabe40b9b0d885340a2a991a44c8a645624075ad966d21f88688e2b69e"
[[package]]
name = "flate2"
-version = "1.0.27"
+version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010"
+checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -2074,7 +2254,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -2134,7 +2314,7 @@ dependencies = [
[[package]]
name = "gen-headers"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"log",
"regex",
@@ -2142,7 +2322,7 @@ dependencies = [
[[package]]
name = "gen-syscall-list"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"regex",
]
@@ -2260,9 +2440,9 @@ dependencies = [
[[package]]
name = "h2"
-version = "0.3.18"
+version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21"
+checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
dependencies = [
"bytes",
"fnv",
@@ -2270,7 +2450,7 @@ dependencies = [
"futures-sink",
"futures-util",
"http",
- "indexmap 1.9.3",
+ "indexmap 2.0.2",
"slab",
"tokio",
"tokio-util 0.7.1",
@@ -2316,14 +2496,14 @@ version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
dependencies = [
- "ahash 0.8.3",
+ "ahash 0.8.5",
]
[[package]]
name = "hashbrown"
-version = "0.14.0"
+version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
+checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12"
[[package]]
name = "headers"
@@ -2626,12 +2806,12 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "2.0.1"
+version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad227c3af19d4914570ad36d30409928b75967c298feb9ea1969db3a610bb14e"
+checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
dependencies = [
"equivalent",
- "hashbrown 0.14.0",
+ "hashbrown 0.14.1",
"rayon",
]
@@ -2868,9 +3048,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
-version = "0.2.148"
+version = "0.2.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
+checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
[[package]]
name = "libloading"
@@ -2964,12 +3144,13 @@ dependencies = [
[[package]]
name = "light-poseidon"
-version = "0.1.1"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "949bdd22e4ed93481d45e9a6badb34b99132bcad0c8a8d4f05c42f7dcc7b90bc"
+checksum = "3c9a85a9752c549ceb7578064b4ed891179d20acd85f27318573b64d2d7ee7ee"
dependencies = [
"ark-bn254",
"ark-ff",
+ "num-bigint 0.4.4",
"thiserror",
]
@@ -2987,10 +3168,11 @@ checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
[[package]]
name = "lock_api"
-version = "0.4.6"
+version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
+checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
dependencies = [
+ "autocfg",
"scopeguard",
]
@@ -3301,13 +3483,13 @@ dependencies = [
[[package]]
name = "num-derive"
-version = "0.4.0"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e6a0fd4f737c707bd9086cc16c925f294943eb62eb71499e9fd4cf71f8b9f4e"
+checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -3345,9 +3527,9 @@ dependencies = [
[[package]]
name = "num-traits"
-version = "0.2.16"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
+checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
"libm",
@@ -3383,11 +3565,11 @@ dependencies = [
[[package]]
name = "num_enum"
-version = "0.7.0"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70bf6736f74634d299d00086f02986875b3c2d924781a6a2cb6c201e73da0ceb"
+checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0"
dependencies = [
- "num_enum_derive 0.7.0",
+ "num_enum_derive 0.7.1",
]
[[package]]
@@ -3411,19 +3593,19 @@ dependencies = [
"proc-macro-crate 1.1.0",
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
name = "num_enum_derive"
-version = "0.7.0"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597"
+checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e"
dependencies = [
"proc-macro-crate 1.1.0",
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -3617,7 +3799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
- "parking_lot_core 0.9.1",
+ "parking_lot_core 0.9.8",
]
[[package]]
@@ -3636,15 +3818,15 @@ dependencies = [
[[package]]
name = "parking_lot_core"
-version = "0.9.1"
+version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954"
+checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
dependencies = [
"cfg-if 1.0.0",
"libc",
- "redox_syscall 0.2.10",
+ "redox_syscall 0.3.5",
"smallvec",
- "windows-sys 0.32.0",
+ "windows-targets 0.48.0",
]
[[package]]
@@ -3792,9 +3974,9 @@ dependencies = [
[[package]]
name = "pin-project-lite"
-version = "0.2.7"
+version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
+checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
@@ -3930,7 +4112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ceca8aaf45b5c46ec7ed39fff75f57290368c1846d33d24a122ca81416ab058"
dependencies = [
"proc-macro2",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -3978,28 +4160,28 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.67"
+version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
+checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [
"unicode-ident",
]
[[package]]
name = "proptest"
-version = "1.2.0"
+version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65"
+checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e"
dependencies = [
"bit-set",
- "bitflags 1.3.2",
- "byteorder",
+ "bit-vec",
+ "bitflags 2.3.3",
"lazy_static",
"num-traits",
"rand 0.8.5",
"rand_chacha 0.3.1",
"rand_xorshift",
- "regex-syntax 0.6.29",
+ "regex-syntax 0.7.5",
"rusty-fork",
"tempfile",
"unarray",
@@ -4061,7 +4243,7 @@ dependencies = [
[[package]]
name = "proto"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"protobuf-src",
"tonic-build",
@@ -4093,7 +4275,7 @@ checksum = "9e2e25ee72f5b24d773cae88422baddefff7714f97aab68d96fe2b6fc4a28fb2"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -4145,7 +4327,7 @@ checksum = "6df19e284d93757a9fb91d63672f7741b129246a669db09d1c0063071debc0c0"
dependencies = [
"bytes",
"libc",
- "socket2 0.5.4",
+ "socket2 0.5.5",
"tracing",
"windows-sys 0.48.0",
]
@@ -4284,9 +4466,9 @@ checksum = "655b020bbf5c89791160a30f0d4706d8ec7aa5718d6a198f6df19c400e4f4470"
[[package]]
name = "rayon"
-version = "1.7.0"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
dependencies = [
"either",
"rayon-core",
@@ -4294,19 +4476,17 @@ dependencies = [
[[package]]
name = "rayon-core"
-version = "1.11.0"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
dependencies = [
- "crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
- "num_cpus",
]
[[package]]
name = "rbpf-cli"
-version = "1.17.0"
+version = "1.17.30"
[[package]]
name = "rcgen"
@@ -4374,14 +4554,14 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.9.6"
+version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff"
+checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
dependencies = [
"aho-corasick 1.0.1",
"memchr",
- "regex-automata 0.3.9",
- "regex-syntax 0.7.5",
+ "regex-automata 0.4.3",
+ "regex-syntax 0.8.2",
]
[[package]]
@@ -4392,32 +4572,32 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-automata"
-version = "0.3.9"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9"
+checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
dependencies = [
"aho-corasick 1.0.1",
"memchr",
- "regex-syntax 0.7.5",
+ "regex-syntax 0.8.2",
]
[[package]]
name = "regex-syntax"
-version = "0.6.29"
+version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
+checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
[[package]]
name = "regex-syntax"
-version = "0.7.5"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
+checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "reqwest"
-version = "0.11.20"
+version = "0.11.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1"
+checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b"
dependencies = [
"async-compression",
"base64 0.21.4",
@@ -4444,6 +4624,7 @@ dependencies = [
"serde",
"serde_json",
"serde_urlencoded",
+ "system-configuration",
"tokio",
"tokio-native-tls",
"tokio-rustls",
@@ -4539,7 +4720,7 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
- "semver 1.0.19",
+ "semver 1.0.20",
]
[[package]]
@@ -4729,9 +4910,9 @@ dependencies = [
[[package]]
name = "semver"
-version = "1.0.19"
+version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0"
+checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
dependencies = [
"serde",
]
@@ -4747,9 +4928,9 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.188"
+version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
+checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
dependencies = [
"serde_derive",
]
@@ -4765,13 +4946,13 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.188"
+version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
+checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -4816,7 +4997,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -4837,7 +5018,7 @@ version = "0.9.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574"
dependencies = [
- "indexmap 2.0.1",
+ "indexmap 2.0.2",
"itoa",
"ryu",
"serde",
@@ -4850,7 +5031,7 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e56dd856803e253c8f298af3f4d7eb0ae5e23a737252cd90bb4f3b435033b2d"
dependencies = [
- "dashmap 5.2.0",
+ "dashmap 5.5.3",
"futures 0.3.28",
"lazy_static",
"log",
@@ -4866,7 +5047,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -4931,9 +5112,9 @@ dependencies = [
[[package]]
name = "sha2"
-version = "0.10.7"
+version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if 1.0.0",
"cpufeatures",
@@ -4979,9 +5160,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
[[package]]
name = "shlex"
-version = "1.1.0"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook"
@@ -5038,9 +5219,9 @@ checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
[[package]]
name = "smallvec"
-version = "1.7.0"
+version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
+checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
[[package]]
name = "smpl_jwt"
@@ -5070,9 +5251,9 @@ dependencies = [
[[package]]
name = "socket2"
-version = "0.5.4"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e"
+checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
dependencies = [
"libc",
"windows-sys 0.48.0",
@@ -5095,7 +5276,7 @@ dependencies = [
[[package]]
name = "solana-account-decoder"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"Inflector",
"assert_matches",
@@ -5112,6 +5293,7 @@ dependencies = [
"spl-pod",
"spl-token",
"spl-token-2022",
+ "spl-token-group-interface",
"spl-token-metadata-interface",
"thiserror",
"zstd",
@@ -5119,7 +5301,7 @@ dependencies = [
[[package]]
name = "solana-accounts-bench"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"clap 2.33.3",
"log",
@@ -5133,7 +5315,7 @@ dependencies = [
[[package]]
name = "solana-accounts-cluster-bench"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"clap 2.33.3",
"log",
@@ -5163,7 +5345,7 @@ dependencies = [
[[package]]
name = "solana-accounts-db"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"arrayref",
"assert_matches",
@@ -5227,7 +5409,7 @@ dependencies = [
[[package]]
name = "solana-address-lookup-table-program"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bincode",
"bytemuck",
@@ -5246,7 +5428,7 @@ dependencies = [
[[package]]
name = "solana-address-lookup-table-program-tests"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"bincode",
@@ -5257,7 +5439,7 @@ dependencies = [
[[package]]
name = "solana-banking-bench"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"clap 3.2.23",
"crossbeam-channel",
@@ -5281,7 +5463,7 @@ dependencies = [
[[package]]
name = "solana-banks-client"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"borsh 0.10.3",
"futures 0.3.28",
@@ -5298,7 +5480,7 @@ dependencies = [
[[package]]
name = "solana-banks-interface"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"serde",
"solana-sdk",
@@ -5307,7 +5489,7 @@ dependencies = [
[[package]]
name = "solana-banks-server"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bincode",
"crossbeam-channel",
@@ -5325,7 +5507,7 @@ dependencies = [
[[package]]
name = "solana-bench-streamer"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"clap 3.2.23",
"crossbeam-channel",
@@ -5336,7 +5518,7 @@ dependencies = [
[[package]]
name = "solana-bench-tps"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"clap 2.33.3",
"crossbeam-channel",
@@ -5377,7 +5559,7 @@ dependencies = [
[[package]]
name = "solana-bloom"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bv",
"fnv",
@@ -5394,7 +5576,7 @@ dependencies = [
[[package]]
name = "solana-bpf-loader-program"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"bincode",
@@ -5409,12 +5591,13 @@ dependencies = [
"solana-sdk",
"solana-zk-token-sdk",
"solana_rbpf",
+ "test-case",
"thiserror",
]
[[package]]
name = "solana-bpf-loader-program-tests"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"bincode",
@@ -5425,7 +5608,7 @@ dependencies = [
[[package]]
name = "solana-bucket-map"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bv",
"bytemuck",
@@ -5444,7 +5627,7 @@ dependencies = [
[[package]]
name = "solana-cargo-build-bpf"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"log",
"solana-logger",
@@ -5452,7 +5635,7 @@ dependencies = [
[[package]]
name = "solana-cargo-build-sbf"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_cmd",
"bzip2",
@@ -5463,7 +5646,7 @@ dependencies = [
"predicates",
"regex",
"reqwest",
- "semver 1.0.19",
+ "semver 1.0.20",
"serial_test",
"solana-download-utils",
"solana-logger",
@@ -5473,11 +5656,11 @@ dependencies = [
[[package]]
name = "solana-cargo-test-bpf"
-version = "1.17.0"
+version = "1.17.30"
[[package]]
name = "solana-cargo-test-sbf"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"cargo_metadata",
"clap 3.2.23",
@@ -5488,7 +5671,7 @@ dependencies = [
[[package]]
name = "solana-clap-utils"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"chrono",
@@ -5505,7 +5688,7 @@ dependencies = [
[[package]]
name = "solana-clap-v3-utils"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"chrono",
@@ -5523,7 +5706,7 @@ dependencies = [
[[package]]
name = "solana-cli"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"bincode",
@@ -5540,7 +5723,7 @@ dependencies = [
"num-traits",
"pretty-hex",
"reqwest",
- "semver 1.0.19",
+ "semver 1.0.20",
"serde",
"serde_derive",
"serde_json",
@@ -5576,7 +5759,7 @@ dependencies = [
[[package]]
name = "solana-cli-config"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"anyhow",
"dirs-next",
@@ -5591,7 +5774,7 @@ dependencies = [
[[package]]
name = "solana-cli-output"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"Inflector",
"base64 0.21.4",
@@ -5602,7 +5785,7 @@ dependencies = [
"humantime",
"indicatif",
"pretty-hex",
- "semver 1.0.19",
+ "semver 1.0.20",
"serde",
"serde_json",
"solana-account-decoder",
@@ -5617,7 +5800,7 @@ dependencies = [
[[package]]
name = "solana-client"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"async-trait",
"bincode",
@@ -5625,7 +5808,7 @@ dependencies = [
"dashmap 4.0.2",
"futures 0.3.28",
"futures-util",
- "indexmap 2.0.1",
+ "indexmap 2.0.2",
"indicatif",
"log",
"quinn",
@@ -5649,7 +5832,7 @@ dependencies = [
[[package]]
name = "solana-client-test"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"futures-util",
"rand 0.8.5",
@@ -5679,7 +5862,7 @@ dependencies = [
[[package]]
name = "solana-compute-budget-program"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"solana-program-runtime",
"solana-sdk",
@@ -5687,7 +5870,7 @@ dependencies = [
[[package]]
name = "solana-config-program"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bincode",
"chrono",
@@ -5700,13 +5883,13 @@ dependencies = [
[[package]]
name = "solana-connection-cache"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"async-trait",
"bincode",
"crossbeam-channel",
"futures-util",
- "indexmap 2.0.1",
+ "indexmap 2.0.2",
"indicatif",
"log",
"rand 0.8.5",
@@ -5724,7 +5907,7 @@ dependencies = [
[[package]]
name = "solana-core"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"base64 0.21.4",
@@ -5807,7 +5990,7 @@ dependencies = [
[[package]]
name = "solana-cost-model"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"lazy_static",
"log",
@@ -5832,7 +6015,7 @@ dependencies = [
[[package]]
name = "solana-dos"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bincode",
"clap 3.2.23",
@@ -5862,7 +6045,7 @@ dependencies = [
[[package]]
name = "solana-download-utils"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"console",
"indicatif",
@@ -5874,7 +6057,7 @@ dependencies = [
[[package]]
name = "solana-ed25519-program-tests"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"ed25519-dalek",
@@ -5885,7 +6068,7 @@ dependencies = [
[[package]]
name = "solana-entry"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"bincode",
@@ -5907,7 +6090,7 @@ dependencies = [
[[package]]
name = "solana-faucet"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bincode",
"byteorder",
@@ -5929,9 +6112,10 @@ dependencies = [
[[package]]
name = "solana-frozen-abi"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
- "ahash 0.8.3",
+ "ahash 0.8.5",
+ "bitflags 2.3.3",
"blake3",
"block-buffer 0.10.4",
"bs58",
@@ -5949,7 +6133,7 @@ dependencies = [
"serde_bytes",
"serde_derive",
"serde_json",
- "sha2 0.10.7",
+ "sha2 0.10.8",
"solana-frozen-abi-macro",
"solana-logger",
"subtle",
@@ -5958,17 +6142,17 @@ dependencies = [
[[package]]
name = "solana-frozen-abi-macro"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"proc-macro2",
"quote",
"rustc_version 0.4.0",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
name = "solana-genesis"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"base64 0.21.4",
"bincode",
@@ -5993,7 +6177,7 @@ dependencies = [
[[package]]
name = "solana-genesis-utils"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"log",
"solana-accounts-db",
@@ -6002,20 +6186,11 @@ dependencies = [
"solana-sdk",
]
-[[package]]
-name = "solana-geyser-plugin-interface"
-version = "1.17.0"
-dependencies = [
- "log",
- "solana-sdk",
- "solana-transaction-status",
- "thiserror",
-]
-
[[package]]
name = "solana-geyser-plugin-manager"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
+ "agave-geyser-plugin-interface",
"bs58",
"crossbeam-channel",
"json5",
@@ -6026,7 +6201,6 @@ dependencies = [
"serde_json",
"solana-accounts-db",
"solana-entry",
- "solana-geyser-plugin-interface",
"solana-ledger",
"solana-measure",
"solana-metrics",
@@ -6039,7 +6213,7 @@ dependencies = [
[[package]]
name = "solana-gossip"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"bincode",
@@ -6047,7 +6221,7 @@ dependencies = [
"clap 2.33.3",
"crossbeam-channel",
"flate2",
- "indexmap 2.0.1",
+ "indexmap 2.0.2",
"itertools",
"log",
"lru",
@@ -6088,44 +6262,9 @@ dependencies = [
"thiserror",
]
-[[package]]
-name = "solana-install"
-version = "1.17.0"
-dependencies = [
- "atty",
- "bincode",
- "bzip2",
- "chrono",
- "clap 2.33.3",
- "console",
- "crossbeam-channel",
- "ctrlc",
- "dirs-next",
- "indicatif",
- "lazy_static",
- "nix 0.26.4",
- "reqwest",
- "scopeguard",
- "semver 1.0.19",
- "serde",
- "serde_yaml 0.8.26",
- "serde_yaml 0.9.25",
- "solana-clap-utils",
- "solana-config-program",
- "solana-logger",
- "solana-rpc-client",
- "solana-sdk",
- "solana-version",
- "tar",
- "tempfile",
- "url 2.4.1",
- "winapi 0.3.9",
- "winreg",
-]
-
[[package]]
name = "solana-keygen"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bs58",
"clap 3.2.23",
@@ -6142,7 +6281,7 @@ dependencies = [
[[package]]
name = "solana-ledger"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"bincode",
@@ -6172,7 +6311,7 @@ dependencies = [
"scopeguard",
"serde",
"serde_bytes",
- "sha2 0.10.7",
+ "sha2 0.10.8",
"solana-account-decoder",
"solana-accounts-db",
"solana-bpf-loader-program",
@@ -6208,58 +6347,9 @@ dependencies = [
"trees",
]
-[[package]]
-name = "solana-ledger-tool"
-version = "1.17.0"
-dependencies = [
- "assert_cmd",
- "bs58",
- "bytecount",
- "chrono",
- "clap 2.33.3",
- "crossbeam-channel",
- "csv",
- "dashmap 4.0.2",
- "futures 0.3.28",
- "histogram",
- "itertools",
- "log",
- "num_cpus",
- "regex",
- "serde",
- "serde_json",
- "signal-hook",
- "solana-account-decoder",
- "solana-accounts-db",
- "solana-bpf-loader-program",
- "solana-clap-utils",
- "solana-cli-output",
- "solana-core",
- "solana-cost-model",
- "solana-entry",
- "solana-geyser-plugin-manager",
- "solana-gossip",
- "solana-ledger",
- "solana-logger",
- "solana-measure",
- "solana-program-runtime",
- "solana-rpc",
- "solana-runtime",
- "solana-sdk",
- "solana-stake-program",
- "solana-storage-bigtable",
- "solana-streamer",
- "solana-transaction-status",
- "solana-version",
- "solana-vote-program",
- "solana_rbpf",
- "tikv-jemallocator",
- "tokio",
-]
-
[[package]]
name = "solana-loader-v4-program"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bincode",
"log",
@@ -6271,7 +6361,7 @@ dependencies = [
[[package]]
name = "solana-local-cluster"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"crossbeam-channel",
@@ -6310,7 +6400,7 @@ dependencies = [
[[package]]
name = "solana-log-analyzer"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"byte-unit",
"clap 3.2.23",
@@ -6322,7 +6412,7 @@ dependencies = [
[[package]]
name = "solana-logger"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"env_logger",
"lazy_static",
@@ -6331,7 +6421,7 @@ dependencies = [
[[package]]
name = "solana-measure"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"log",
"solana-sdk",
@@ -6339,11 +6429,11 @@ dependencies = [
[[package]]
name = "solana-memory-management"
-version = "1.17.0"
+version = "1.17.30"
[[package]]
name = "solana-merkle-root-bench"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"clap 2.33.3",
"log",
@@ -6356,7 +6446,7 @@ dependencies = [
[[package]]
name = "solana-merkle-tree"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"fast-math",
"hex",
@@ -6365,7 +6455,7 @@ dependencies = [
[[package]]
name = "solana-metrics"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"crossbeam-channel",
"env_logger",
@@ -6381,7 +6471,7 @@ dependencies = [
[[package]]
name = "solana-net-shaper"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"clap 3.2.23",
"rand 0.8.5",
@@ -6392,7 +6482,7 @@ dependencies = [
[[package]]
name = "solana-net-utils"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bincode",
"clap 3.2.23",
@@ -6402,7 +6492,7 @@ dependencies = [
"rand 0.8.5",
"serde",
"serde_derive",
- "socket2 0.5.4",
+ "socket2 0.5.5",
"solana-logger",
"solana-sdk",
"solana-version",
@@ -6412,7 +6502,7 @@ dependencies = [
[[package]]
name = "solana-notifier"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"log",
"reqwest",
@@ -6422,9 +6512,9 @@ dependencies = [
[[package]]
name = "solana-perf"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
- "ahash 0.8.3",
+ "ahash 0.8.5",
"assert_matches",
"bincode",
"bv",
@@ -6439,7 +6529,10 @@ dependencies = [
"rand 0.8.5",
"rand_chacha 0.3.1",
"rayon",
+ "rustc_version 0.4.0",
"serde",
+ "solana-frozen-abi",
+ "solana-frozen-abi-macro",
"solana-logger",
"solana-metrics",
"solana-rayon-threadlimit",
@@ -6450,7 +6543,7 @@ dependencies = [
[[package]]
name = "solana-poh"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"bincode",
@@ -6471,7 +6564,7 @@ dependencies = [
[[package]]
name = "solana-poh-bench"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"clap 3.2.23",
"log",
@@ -6486,7 +6579,7 @@ dependencies = [
[[package]]
name = "solana-program"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"anyhow",
"ark-bn254",
@@ -6528,7 +6621,7 @@ dependencies = [
"serde_bytes",
"serde_derive",
"serde_json",
- "sha2 0.10.7",
+ "sha2 0.10.8",
"sha3 0.10.4",
"solana-frozen-abi",
"solana-frozen-abi-macro",
@@ -6543,7 +6636,7 @@ dependencies = [
[[package]]
name = "solana-program-runtime"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"base64 0.21.4",
@@ -6572,7 +6665,7 @@ dependencies = [
[[package]]
name = "solana-program-test"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"async-trait",
@@ -6593,6 +6686,7 @@ dependencies = [
"solana-sdk",
"solana-stake-program",
"solana-vote-program",
+ "solana_rbpf",
"test-case",
"thiserror",
"tokio",
@@ -6600,14 +6694,14 @@ dependencies = [
[[package]]
name = "solana-pubsub-client"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"anyhow",
"crossbeam-channel",
"futures-util",
"log",
"reqwest",
- "semver 1.0.19",
+ "semver 1.0.20",
"serde",
"serde_derive",
"serde_json",
@@ -6624,7 +6718,7 @@ dependencies = [
[[package]]
name = "solana-quic-client"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"async-mutex",
"async-trait",
@@ -6652,7 +6746,7 @@ dependencies = [
[[package]]
name = "solana-rayon-threadlimit"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"lazy_static",
"num_cpus",
@@ -6660,7 +6754,7 @@ dependencies = [
[[package]]
name = "solana-remote-wallet"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"console",
@@ -6671,7 +6765,7 @@ dependencies = [
"num-traits",
"parking_lot 0.12.1",
"qstring",
- "semver 1.0.19",
+ "semver 1.0.20",
"solana-sdk",
"thiserror",
"uriparse",
@@ -6679,7 +6773,7 @@ dependencies = [
[[package]]
name = "solana-rpc"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"base64 0.21.4",
"bincode",
@@ -6738,7 +6832,7 @@ dependencies = [
[[package]]
name = "solana-rpc-client"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"async-trait",
@@ -6752,7 +6846,7 @@ dependencies = [
"jsonrpc-http-server",
"log",
"reqwest",
- "semver 1.0.19",
+ "semver 1.0.20",
"serde",
"serde_derive",
"serde_json",
@@ -6767,13 +6861,13 @@ dependencies = [
[[package]]
name = "solana-rpc-client-api"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"base64 0.21.4",
"bs58",
"jsonrpc-core",
"reqwest",
- "semver 1.0.19",
+ "semver 1.0.20",
"serde",
"serde_derive",
"serde_json",
@@ -6787,7 +6881,7 @@ dependencies = [
[[package]]
name = "solana-rpc-client-nonce-utils"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"anyhow",
"clap 2.33.3",
@@ -6804,7 +6898,7 @@ dependencies = [
[[package]]
name = "solana-rpc-test"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bincode",
"bs58",
@@ -6831,7 +6925,7 @@ dependencies = [
[[package]]
name = "solana-runtime"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"arrayref",
"assert_matches",
@@ -6914,7 +7008,7 @@ dependencies = [
[[package]]
name = "solana-sdk"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"anyhow",
"assert_matches",
@@ -6955,7 +7049,7 @@ dependencies = [
"serde_derive",
"serde_json",
"serde_with",
- "sha2 0.10.7",
+ "sha2 0.10.8",
"sha3 0.10.4",
"solana-frozen-abi",
"solana-frozen-abi-macro",
@@ -6972,18 +7066,24 @@ dependencies = [
[[package]]
name = "solana-sdk-macro"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bs58",
"proc-macro2",
"quote",
"rustversion",
- "syn 2.0.37",
+ "syn 2.0.38",
]
+[[package]]
+name = "solana-security-txt"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "468aa43b7edb1f9b7b7b686d5c3aeb6630dc1708e86e31343499dd5c4d775183"
+
[[package]]
name = "solana-send-transaction-service"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"crossbeam-channel",
"log",
@@ -6998,7 +7098,7 @@ dependencies = [
[[package]]
name = "solana-stake-accounts"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"clap 2.33.3",
"solana-clap-utils",
@@ -7014,7 +7114,7 @@ dependencies = [
[[package]]
name = "solana-stake-program"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"bincode",
@@ -7031,7 +7131,7 @@ dependencies = [
[[package]]
name = "solana-storage-bigtable"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"backoff",
"bincode",
@@ -7063,7 +7163,7 @@ dependencies = [
[[package]]
name = "solana-storage-proto"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bincode",
"bs58",
@@ -7079,7 +7179,7 @@ dependencies = [
[[package]]
name = "solana-store-tool"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"clap 2.33.3",
"log",
@@ -7091,15 +7191,16 @@ dependencies = [
[[package]]
name = "solana-streamer"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"async-channel",
"bytes",
"crossbeam-channel",
+ "futures 0.3.28",
"futures-util",
"histogram",
- "indexmap 2.0.1",
+ "indexmap 2.0.2",
"itertools",
"libc",
"log",
@@ -7112,6 +7213,7 @@ dependencies = [
"rand 0.8.5",
"rcgen",
"rustls",
+ "socket2 0.5.5",
"solana-logger",
"solana-metrics",
"solana-perf",
@@ -7123,7 +7225,7 @@ dependencies = [
[[package]]
name = "solana-system-program"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"bincode",
@@ -7137,7 +7239,7 @@ dependencies = [
[[package]]
name = "solana-test-validator"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"base64 0.21.4",
"bincode",
@@ -7167,7 +7269,7 @@ dependencies = [
[[package]]
name = "solana-thin-client"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bincode",
"log",
@@ -7181,7 +7283,7 @@ dependencies = [
[[package]]
name = "solana-tokens"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"bincode",
@@ -7190,7 +7292,7 @@ dependencies = [
"console",
"csv",
"ctrlc",
- "indexmap 2.0.1",
+ "indexmap 2.0.2",
"indicatif",
"pickledb",
"serde",
@@ -7214,12 +7316,12 @@ dependencies = [
[[package]]
name = "solana-tpu-client"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"async-trait",
"bincode",
"futures-util",
- "indexmap 2.0.1",
+ "indexmap 2.0.2",
"indicatif",
"log",
"rayon",
@@ -7236,7 +7338,7 @@ dependencies = [
[[package]]
name = "solana-transaction-dos"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bincode",
"clap 2.33.3",
@@ -7263,7 +7365,7 @@ dependencies = [
[[package]]
name = "solana-transaction-status"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"Inflector",
"base64 0.21.4",
@@ -7286,7 +7388,7 @@ dependencies = [
[[package]]
name = "solana-turbine"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"bincode",
@@ -7323,7 +7425,7 @@ dependencies = [
[[package]]
name = "solana-udp-client"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"async-trait",
"solana-connection-cache",
@@ -7336,83 +7438,19 @@ dependencies = [
[[package]]
name = "solana-upload-perf"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"serde_json",
"solana-metrics",
]
-[[package]]
-name = "solana-validator"
-version = "1.17.0"
-dependencies = [
- "chrono",
- "clap 2.33.3",
- "console",
- "core_affinity",
- "crossbeam-channel",
- "fd-lock",
- "indicatif",
- "itertools",
- "jsonrpc-core",
- "jsonrpc-core-client",
- "jsonrpc-derive",
- "jsonrpc-ipc-server",
- "jsonrpc-server-utils",
- "lazy_static",
- "libc",
- "libloading",
- "log",
- "num_cpus",
- "rand 0.8.5",
- "rayon",
- "serde",
- "serde_json",
- "serde_yaml 0.9.25",
- "signal-hook",
- "solana-account-decoder",
- "solana-accounts-db",
- "solana-clap-utils",
- "solana-cli-config",
- "solana-core",
- "solana-download-utils",
- "solana-entry",
- "solana-faucet",
- "solana-genesis-utils",
- "solana-geyser-plugin-interface",
- "solana-geyser-plugin-manager",
- "solana-gossip",
- "solana-ledger",
- "solana-logger",
- "solana-metrics",
- "solana-net-utils",
- "solana-perf",
- "solana-poh",
- "solana-rpc",
- "solana-rpc-client",
- "solana-rpc-client-api",
- "solana-runtime",
- "solana-sdk",
- "solana-send-transaction-service",
- "solana-storage-bigtable",
- "solana-streamer",
- "solana-test-validator",
- "solana-tpu-client",
- "solana-version",
- "solana-vote-program",
- "spl-token-2022",
- "symlink",
- "thiserror",
- "tikv-jemallocator",
-]
-
[[package]]
name = "solana-version"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"log",
"rustc_version 0.4.0",
- "semver 1.0.19",
+ "semver 1.0.20",
"serde",
"serde_derive",
"solana-frozen-abi",
@@ -7422,7 +7460,7 @@ dependencies = [
[[package]]
name = "solana-vote"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bincode",
"crossbeam-channel",
@@ -7441,7 +7479,7 @@ dependencies = [
[[package]]
name = "solana-vote-program"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"assert_matches",
"bincode",
@@ -7462,28 +7500,9 @@ dependencies = [
"thiserror",
]
-[[package]]
-name = "solana-watchtower"
-version = "1.17.0"
-dependencies = [
- "clap 2.33.3",
- "humantime",
- "log",
- "solana-clap-utils",
- "solana-cli-config",
- "solana-cli-output",
- "solana-logger",
- "solana-metrics",
- "solana-notifier",
- "solana-rpc-client",
- "solana-rpc-client-api",
- "solana-sdk",
- "solana-version",
-]
-
[[package]]
name = "solana-zk-keygen"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bs58",
"clap 3.2.23",
@@ -7502,7 +7521,7 @@ dependencies = [
[[package]]
name = "solana-zk-token-proof-program"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bytemuck",
"criterion",
@@ -7516,7 +7535,7 @@ dependencies = [
[[package]]
name = "solana-zk-token-proof-program-tests"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"bytemuck",
"curve25519-dalek",
@@ -7528,7 +7547,7 @@ dependencies = [
[[package]]
name = "solana-zk-token-sdk"
-version = "1.17.0"
+version = "1.17.30"
dependencies = [
"aes-gcm-siv",
"base64 0.21.4",
@@ -7556,9 +7575,9 @@ dependencies = [
[[package]]
name = "solana_rbpf"
-version = "0.7.2"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "103318aa365ff7caa8cf534f2246b5eb7e5b34668736d52b1266b143f7a21196"
+checksum = "3d457cc2ba742c120492a64b7fa60e22c575e891f6b55039f4d736568fb112a3"
dependencies = [
"byteorder",
"combine",
@@ -7598,13 +7617,13 @@ dependencies = [
[[package]]
name = "spl-associated-token-account"
-version = "2.2.0"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "385e31c29981488f2820b2022d8e731aae3b02e6e18e2fd854e4c9a94dc44fc3"
+checksum = "992d9c64c2564cc8f63a4b508bf3ebcdf2254b0429b13cd1d31adb6162432a5f"
dependencies = [
"assert_matches",
"borsh 0.10.3",
- "num-derive 0.4.0",
+ "num-derive 0.4.1",
"num-traits",
"solana-program",
"spl-token",
@@ -7631,7 +7650,7 @@ checksum = "fadbefec4f3c678215ca72bd71862697bb06b41fd77c0088902dd3203354387b"
dependencies = [
"quote",
"spl-discriminator-syn",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -7642,8 +7661,8 @@ checksum = "0e5f2044ca42c8938d54d1255ce599c79a1ffd86b677dfab695caa20f9ffc3f2"
dependencies = [
"proc-macro2",
"quote",
- "sha2 0.10.7",
- "syn 2.0.37",
+ "sha2 0.10.8",
+ "syn 2.0.38",
"thiserror",
]
@@ -7685,7 +7704,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "249e0318493b6bcf27ae9902600566c689b7dfba9f1bdff5893e92253374e78c"
dependencies = [
- "num-derive 0.4.0",
+ "num-derive 0.4.1",
"num-traits",
"solana-program",
"spl-program-error-derive",
@@ -7700,15 +7719,15 @@ checksum = "ab5269c8e868da17b6552ef35a51355a017bd8e0eae269c201fef830d35fa52c"
dependencies = [
"proc-macro2",
"quote",
- "sha2 0.10.7",
- "syn 2.0.37",
+ "sha2 0.10.8",
+ "syn 2.0.38",
]
[[package]]
name = "spl-tlv-account-resolution"
-version = "0.4.0"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "062e148d3eab7b165582757453632ffeef490c02c86a48bfdb4988f63eefb3b9"
+checksum = "3f7020347c07892c08560d230fbb8a980316c9e198e22b198b7b9d951ff96047"
dependencies = [
"bytemuck",
"solana-program",
@@ -7735,26 +7754,41 @@ dependencies = [
[[package]]
name = "spl-token-2022"
-version = "0.9.0"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4abf34a65ba420584a0c35f3903f8d727d1f13ababbdc3f714c6b065a686e86"
+checksum = "d697fac19fd74ff472dfcc13f0b442dd71403178ce1de7b5d16f83a33561c059"
dependencies = [
"arrayref",
"bytemuck",
- "num-derive 0.4.0",
+ "num-derive 0.4.1",
"num-traits",
- "num_enum 0.7.0",
+ "num_enum 0.7.1",
"solana-program",
+ "solana-security-txt",
"solana-zk-token-sdk",
"spl-memo",
"spl-pod",
"spl-token",
+ "spl-token-group-interface",
"spl-token-metadata-interface",
"spl-transfer-hook-interface",
"spl-type-length-value",
"thiserror",
]
+[[package]]
+name = "spl-token-group-interface"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b889509d49fa74a4a033ca5dae6c2307e9e918122d97e58562f5c4ffa795c75d"
+dependencies = [
+ "bytemuck",
+ "solana-program",
+ "spl-discriminator",
+ "spl-pod",
+ "spl-program-error",
+]
+
[[package]]
name = "spl-token-metadata-interface"
version = "0.2.0"
@@ -7771,9 +7805,9 @@ dependencies = [
[[package]]
name = "spl-transfer-hook-interface"
-version = "0.3.0"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "051d31803f873cabe71aec3c1b849f35248beae5d19a347d93a5c9cccc5d5a9b"
+checksum = "7aabdb7c471566f6ddcee724beb8618449ea24b399e58d464d6b5bc7db550259"
dependencies = [
"arrayref",
"bytemuck",
@@ -7874,9 +7908,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.37"
+version = "2.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8"
+checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
dependencies = [
"proc-macro2",
"quote",
@@ -7924,6 +7958,27 @@ dependencies = [
"walkdir",
]
+[[package]]
+name = "system-configuration"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
+dependencies = [
+ "bitflags 1.3.2",
+ "core-foundation",
+ "system-configuration-sys",
+]
+
+[[package]]
+name = "system-configuration-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
[[package]]
name = "systemstat"
version = "0.2.3"
@@ -8031,7 +8086,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -8043,7 +8098,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
"test-case-core",
]
@@ -8064,22 +8119,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
[[package]]
name = "thiserror"
-version = "1.0.49"
+version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4"
+checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.49"
+version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc"
+checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -8183,8 +8238,7 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
version = "1.29.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
+source = "git+https://github.com/solana-labs/solana-tokio.git?rev=7cf47705faacf7bf0e43e4131a5377b3291fce21#7cf47705faacf7bf0e43e4131a5377b3291fce21"
dependencies = [
"autocfg",
"backtrace",
@@ -8213,12 +8267,11 @@ dependencies = [
[[package]]
name = "tokio-macros"
version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
+source = "git+https://github.com/solana-labs/solana-tokio.git?rev=7cf47705faacf7bf0e43e4131a5377b3291fce21#7cf47705faacf7bf0e43e4131a5377b3291fce21"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
@@ -8400,11 +8453,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
name = "tracing"
-version = "0.1.29"
+version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
- "cfg-if 1.0.0",
"log",
"pin-project-lite",
"tracing-attributes",
@@ -8413,22 +8465,23 @@ dependencies = [
[[package]]
name = "tracing-attributes"
-version = "0.1.18"
+version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e"
+checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.38",
]
[[package]]
name = "tracing-core"
-version = "0.1.21"
+version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
- "lazy_static",
+ "once_cell",
+ "valuable",
]
[[package]]
@@ -8622,6 +8675,12 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cf7d77f457ef8dfa11e4cd5933c5ddb5dc52a94664071951219a97710f0a32b"
+[[package]]
+name = "valuable"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+
[[package]]
name = "vcpkg"
version = "0.2.15"
@@ -8709,7 +8768,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
"wasm-bindgen-shared",
]
@@ -8743,7 +8802,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -8833,19 +8892,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-[[package]]
-name = "windows-sys"
-version = "0.32.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6"
-dependencies = [
- "windows_aarch64_msvc 0.32.0",
- "windows_i686_gnu 0.32.0",
- "windows_i686_msvc 0.32.0",
- "windows_x86_64_gnu 0.32.0",
- "windows_x86_64_msvc 0.32.0",
-]
-
[[package]]
name = "windows-sys"
version = "0.45.0"
@@ -8906,12 +8952,6 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.32.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5"
-
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
@@ -8924,12 +8964,6 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
-[[package]]
-name = "windows_i686_gnu"
-version = "0.32.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615"
-
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
@@ -8942,12 +8976,6 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
-[[package]]
-name = "windows_i686_msvc"
-version = "0.32.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172"
-
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
@@ -8960,12 +8988,6 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.32.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc"
-
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
@@ -8990,12 +9012,6 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.32.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316"
-
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
@@ -9063,6 +9079,26 @@ dependencies = [
"time",
]
+[[package]]
+name = "zerocopy"
+version = "0.7.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.38",
+]
+
[[package]]
name = "zeroize"
version = "1.3.0"
@@ -9080,7 +9116,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.38",
]
[[package]]
diff --git a/Cargo.toml b/Cargo.toml
index a93092f2e89..cb571d72d2f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -123,7 +123,7 @@ exclude = [
resolver = "2"
[workspace.package]
-version = "1.17.0"
+version = "1.17.30"
authors = ["Solana Labs Maintainers "]
repository = "https://github.com/solana-labs/solana"
homepage = "https://solanalabs.com/"
@@ -132,7 +132,7 @@ edition = "2021"
[workspace.dependencies]
aes-gcm-siv = "0.10.3"
-ahash = "0.8.3"
+ahash = "=0.8.5"
anyhow = "1.0.75"
ark-bn254 = "0.4.0"
ark-ec = "0.4.0"
@@ -233,7 +233,7 @@ lazy_static = "1.4.0"
libc = "0.2.148"
libloading = "0.7.4"
libsecp256k1 = "0.6.0"
-light-poseidon = "0.1.1"
+light-poseidon = "0.2.0"
log = "0.4.20"
lru = "0.7.7"
lz4 = "1.24.0"
@@ -296,89 +296,90 @@ sha3 = "0.10.4"
signal-hook = "0.3.17"
siphasher = "0.3.11"
smpl_jwt = "0.7.1"
-socket2 = "0.5.4"
+socket2 = { version= "0.5.4", features=["all"]}
soketto = "0.7"
-solana_rbpf = "=0.7.2"
-solana-account-decoder = { path = "account-decoder", version = "=1.17.0" }
-solana-accounts-db = { path = "accounts-db", version = "=1.17.0" }
-solana-address-lookup-table-program = { path = "programs/address-lookup-table", version = "=1.17.0" }
-solana-banks-client = { path = "banks-client", version = "=1.17.0" }
-solana-banks-interface = { path = "banks-interface", version = "=1.17.0" }
-solana-banks-server = { path = "banks-server", version = "=1.17.0" }
-solana-bench-tps = { path = "bench-tps", version = "=1.17.0" }
-solana-bloom = { path = "bloom", version = "=1.17.0" }
-solana-bpf-loader-program = { path = "programs/bpf_loader", version = "=1.17.0" }
-solana-bucket-map = { path = "bucket_map", version = "=1.17.0" }
-solana-connection-cache = { path = "connection-cache", version = "=1.17.0", default-features = false }
-solana-clap-utils = { path = "clap-utils", version = "=1.17.0" }
-solana-clap-v3-utils = { path = "clap-v3-utils", version = "=1.17.0" }
-solana-cli = { path = "cli", version = "=1.17.0" }
-solana-cli-config = { path = "cli-config", version = "=1.17.0" }
-solana-cli-output = { path = "cli-output", version = "=1.17.0" }
-solana-client = { path = "client", version = "=1.17.0" }
-solana-compute-budget-program = { path = "programs/compute-budget", version = "=1.17.0" }
-solana-config-program = { path = "programs/config", version = "=1.17.0" }
-solana-core = { path = "core", version = "=1.17.0" }
-solana-cost-model = { path = "cost-model", version = "=1.17.0" }
-solana-download-utils = { path = "download-utils", version = "=1.17.0" }
-solana-entry = { path = "entry", version = "=1.17.0" }
-solana-faucet = { path = "faucet", version = "=1.17.0" }
-solana-frozen-abi = { path = "frozen-abi", version = "=1.17.0" }
-solana-frozen-abi-macro = { path = "frozen-abi/macro", version = "=1.17.0" }
-solana-genesis = { path = "genesis", version = "=1.17.0" }
-solana-genesis-utils = { path = "genesis-utils", version = "=1.17.0" }
-solana-geyser-plugin-interface = { path = "geyser-plugin-interface", version = "=1.17.0" }
-solana-geyser-plugin-manager = { path = "geyser-plugin-manager", version = "=1.17.0" }
-solana-gossip = { path = "gossip", version = "=1.17.0" }
-solana-loader-v4-program = { path = "programs/loader-v4", version = "=1.17.0" }
-solana-ledger = { path = "ledger", version = "=1.17.0" }
-solana-local-cluster = { path = "local-cluster", version = "=1.17.0" }
-solana-logger = { path = "logger", version = "=1.17.0" }
-solana-measure = { path = "measure", version = "=1.17.0" }
-solana-merkle-tree = { path = "merkle-tree", version = "=1.17.0" }
-solana-metrics = { path = "metrics", version = "=1.17.0" }
-solana-net-utils = { path = "net-utils", version = "=1.17.0" }
-solana-notifier = { path = "notifier", version = "=1.17.0" }
-solana-perf = { path = "perf", version = "=1.17.0" }
-solana-poh = { path = "poh", version = "=1.17.0" }
-solana-program = { path = "sdk/program", version = "=1.17.0" }
-solana-program-runtime = { path = "program-runtime", version = "=1.17.0" }
-solana-program-test = { path = "program-test", version = "=1.17.0" }
-solana-pubsub-client = { path = "pubsub-client", version = "=1.17.0" }
-solana-quic-client = { path = "quic-client", version = "=1.17.0" }
-solana-rayon-threadlimit = { path = "rayon-threadlimit", version = "=1.17.0" }
-solana-remote-wallet = { path = "remote-wallet", version = "=1.17.0", default-features = false }
-solana-rpc = { path = "rpc", version = "=1.17.0" }
-solana-rpc-client = { path = "rpc-client", version = "=1.17.0", default-features = false }
-solana-rpc-client-api = { path = "rpc-client-api", version = "=1.17.0" }
-solana-rpc-client-nonce-utils = { path = "rpc-client-nonce-utils", version = "=1.17.0" }
-solana-runtime = { path = "runtime", version = "=1.17.0" }
-solana-sdk = { path = "sdk", version = "=1.17.0" }
-solana-sdk-macro = { path = "sdk/macro", version = "=1.17.0" }
-solana-send-transaction-service = { path = "send-transaction-service", version = "=1.17.0" }
-solana-stake-program = { path = "programs/stake", version = "=1.17.0" }
-solana-storage-bigtable = { path = "storage-bigtable", version = "=1.17.0" }
-solana-storage-proto = { path = "storage-proto", version = "=1.17.0" }
-solana-streamer = { path = "streamer", version = "=1.17.0" }
-solana-system-program = { path = "programs/system", version = "=1.17.0" }
-solana-test-validator = { path = "test-validator", version = "=1.17.0" }
-solana-thin-client = { path = "thin-client", version = "=1.17.0" }
-solana-tpu-client = { path = "tpu-client", version = "=1.17.0", default-features = false }
-solana-transaction-status = { path = "transaction-status", version = "=1.17.0" }
-solana-turbine = { path = "turbine", version = "=1.17.0" }
-solana-udp-client = { path = "udp-client", version = "=1.17.0" }
-solana-version = { path = "version", version = "=1.17.0" }
-solana-vote = { path = "vote", version = "=1.17.0" }
-solana-vote-program = { path = "programs/vote", version = "=1.17.0" }
-solana-zk-keygen = { path = "zk-keygen", version = "=1.17.0" }
-solana-zk-token-proof-program = { path = "programs/zk-token-proof", version = "=1.17.0" }
-solana-zk-token-sdk = { path = "zk-token-sdk", version = "=1.17.0" }
-spl-associated-token-account = "=2.2.0"
+solana_rbpf = "=0.8.0"
+solana-account-decoder = { path = "account-decoder", version = "=1.17.30" }
+solana-accounts-db = { path = "accounts-db", version = "=1.17.30" }
+solana-address-lookup-table-program = { path = "programs/address-lookup-table", version = "=1.17.30" }
+solana-banks-client = { path = "banks-client", version = "=1.17.30" }
+solana-banks-interface = { path = "banks-interface", version = "=1.17.30" }
+solana-banks-server = { path = "banks-server", version = "=1.17.30" }
+solana-bench-tps = { path = "bench-tps", version = "=1.17.30" }
+solana-bloom = { path = "bloom", version = "=1.17.30" }
+solana-bpf-loader-program = { path = "programs/bpf_loader", version = "=1.17.30" }
+solana-bucket-map = { path = "bucket_map", version = "=1.17.30" }
+solana-connection-cache = { path = "connection-cache", version = "=1.17.30", default-features = false }
+solana-clap-utils = { path = "clap-utils", version = "=1.17.30" }
+solana-clap-v3-utils = { path = "clap-v3-utils", version = "=1.17.30" }
+solana-cli = { path = "cli", version = "=1.17.30" }
+solana-cli-config = { path = "cli-config", version = "=1.17.30" }
+solana-cli-output = { path = "cli-output", version = "=1.17.30" }
+solana-client = { path = "client", version = "=1.17.30" }
+solana-compute-budget-program = { path = "programs/compute-budget", version = "=1.17.30" }
+solana-config-program = { path = "programs/config", version = "=1.17.30" }
+solana-core = { path = "core", version = "=1.17.30" }
+solana-cost-model = { path = "cost-model", version = "=1.17.30" }
+solana-download-utils = { path = "download-utils", version = "=1.17.30" }
+solana-entry = { path = "entry", version = "=1.17.30" }
+solana-faucet = { path = "faucet", version = "=1.17.30" }
+solana-frozen-abi = { path = "frozen-abi", version = "=1.17.30" }
+solana-frozen-abi-macro = { path = "frozen-abi/macro", version = "=1.17.30" }
+solana-genesis = { path = "genesis", version = "=1.17.30" }
+solana-genesis-utils = { path = "genesis-utils", version = "=1.17.30" }
+agave-geyser-plugin-interface = { path = "geyser-plugin-interface", version = "=1.17.30" }
+solana-geyser-plugin-manager = { path = "geyser-plugin-manager", version = "=1.17.30" }
+solana-gossip = { path = "gossip", version = "=1.17.30" }
+solana-loader-v4-program = { path = "programs/loader-v4", version = "=1.17.30" }
+solana-ledger = { path = "ledger", version = "=1.17.30" }
+solana-local-cluster = { path = "local-cluster", version = "=1.17.30" }
+solana-logger = { path = "logger", version = "=1.17.30" }
+solana-measure = { path = "measure", version = "=1.17.30" }
+solana-merkle-tree = { path = "merkle-tree", version = "=1.17.30" }
+solana-metrics = { path = "metrics", version = "=1.17.30" }
+solana-net-utils = { path = "net-utils", version = "=1.17.30" }
+solana-notifier = { path = "notifier", version = "=1.17.30" }
+solana-perf = { path = "perf", version = "=1.17.30" }
+solana-poh = { path = "poh", version = "=1.17.30" }
+solana-program = { path = "sdk/program", version = "=1.17.30" }
+solana-program-runtime = { path = "program-runtime", version = "=1.17.30" }
+solana-program-test = { path = "program-test", version = "=1.17.30" }
+solana-pubsub-client = { path = "pubsub-client", version = "=1.17.30" }
+solana-quic-client = { path = "quic-client", version = "=1.17.30" }
+solana-rayon-threadlimit = { path = "rayon-threadlimit", version = "=1.17.30" }
+solana-remote-wallet = { path = "remote-wallet", version = "=1.17.30", default-features = false }
+solana-rpc = { path = "rpc", version = "=1.17.30" }
+solana-rpc-client = { path = "rpc-client", version = "=1.17.30", default-features = false }
+solana-rpc-client-api = { path = "rpc-client-api", version = "=1.17.30" }
+solana-rpc-client-nonce-utils = { path = "rpc-client-nonce-utils", version = "=1.17.30" }
+solana-runtime = { path = "runtime", version = "=1.17.30" }
+solana-sdk = { path = "sdk", version = "=1.17.30" }
+solana-sdk-macro = { path = "sdk/macro", version = "=1.17.30" }
+solana-send-transaction-service = { path = "send-transaction-service", version = "=1.17.30" }
+solana-stake-program = { path = "programs/stake", version = "=1.17.30" }
+solana-storage-bigtable = { path = "storage-bigtable", version = "=1.17.30" }
+solana-storage-proto = { path = "storage-proto", version = "=1.17.30" }
+solana-streamer = { path = "streamer", version = "=1.17.30" }
+solana-system-program = { path = "programs/system", version = "=1.17.30" }
+solana-test-validator = { path = "test-validator", version = "=1.17.30" }
+solana-thin-client = { path = "thin-client", version = "=1.17.30" }
+solana-tpu-client = { path = "tpu-client", version = "=1.17.30", default-features = false }
+solana-transaction-status = { path = "transaction-status", version = "=1.17.30" }
+solana-turbine = { path = "turbine", version = "=1.17.30" }
+solana-udp-client = { path = "udp-client", version = "=1.17.30" }
+solana-version = { path = "version", version = "=1.17.30" }
+solana-vote = { path = "vote", version = "=1.17.30" }
+solana-vote-program = { path = "programs/vote", version = "=1.17.30" }
+solana-zk-keygen = { path = "zk-keygen", version = "=1.17.30" }
+solana-zk-token-proof-program = { path = "programs/zk-token-proof", version = "=1.17.30" }
+solana-zk-token-sdk = { path = "zk-token-sdk", version = "=1.17.30" }
+spl-associated-token-account = "=2.3.0"
spl-instruction-padding = "0.1"
spl-memo = "=4.0.0"
spl-pod = "=0.1.0"
spl-token = "=4.0.0"
-spl-token-2022 = "=0.9.0"
+spl-token-2022 = "=1.0.0"
+spl-token-group-interface = "=0.1.0"
spl-token-metadata-interface = "=0.2.0"
static_assertions = "1.1.0"
stream-cancel = "0.8.1"
@@ -396,6 +397,7 @@ tempfile = "3.8.0"
test-case = "3.2.1"
thiserror = "1.0.49"
tiny-bip39 = "0.8.2"
+# Update solana-tokio patch below when updating this version
tokio = "1.29.1"
tokio-serde = "0.8"
tokio-stream = "0.1.14"
@@ -445,3 +447,21 @@ crossbeam-epoch = { git = "https://github.com/solana-labs/crossbeam", rev = "fd2
# overrides in sync.
solana-program = { path = "sdk/program" }
solana-zk-token-sdk = { path = "zk-token-sdk" }
+#
+# Solana RPC nodes experience stalls when running with `tokio` containing this
+# commit:
+# https://github.com/tokio-rs/tokio/commit/4eed411519783ef6f58cbf74f886f91142b5cfa6
+#
+# Tokio maintainers believe performance degradation is due to application bugs:
+# https://github.com/tokio-rs/tokio/issues/4873#issuecomment-1198277677
+#
+# This may indeed be true of the code in this monorepo, but we haven't yet
+# identified the bug or a way to fix. As a stopgap, this patches `tokio` to the
+# tagged version specified above with commit `4eed411` reverted.
+#
+# Comparison:
+# https://github.com/tokio-rs/tokio/compare/tokio-1.29.1...solana-labs:solana-tokio:tokio-1.29.1-revert-4eed411
+#
+[patch.crates-io.tokio]
+git = "https://github.com/solana-labs/solana-tokio.git"
+rev = "7cf47705faacf7bf0e43e4131a5377b3291fce21"
diff --git a/README.md b/README.md
index 4fccacf2ba0..e5e50d5c482 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-
+
@@ -111,35 +111,3 @@ problem is solved by this code?" On the other hand, if a test does fail and you
better way to solve the same problem, a Pull Request with your solution would most certainly be
welcome! Likewise, if rewriting a test can better communicate what code it's protecting, please
send us that patch!
-
-# Disclaimer
-
-All claims, content, designs, algorithms, estimates, roadmaps,
-specifications, and performance measurements described in this project
-are done with the Solana Labs, Inc. (“SL”) good faith efforts. It is up to
-the reader to check and validate their accuracy and truthfulness.
-Furthermore, nothing in this project constitutes a solicitation for
-investment.
-
-Any content produced by SL or developer resources that SL provides are
-for educational and inspirational purposes only. SL does not encourage,
-induce or sanction the deployment, integration or use of any such
-applications (including the code comprising the Solana blockchain
-protocol) in violation of applicable laws or regulations and hereby
-prohibits any such deployment, integration or use. This includes the use of
-any such applications by the reader (a) in violation of export control
-or sanctions laws of the United States or any other applicable
-jurisdiction, (b) if the reader is located in or ordinarily resident in
-a country or territory subject to comprehensive sanctions administered
-by the U.S. Office of Foreign Assets Control (OFAC), or (c) if the
-reader is or is working on behalf of a Specially Designated National
-(SDN) or a person subject to similar blocking or denied party
-prohibitions.
-
-The reader should be aware that U.S. export control and sanctions laws prohibit
-U.S. persons (and other persons that are subject to such laws) from transacting
-with persons in certain countries and territories or that are on the SDN list.
-Accordingly, there is a risk to individuals that other persons using any of the
-code contained in this repo, or a derivation thereof, may be sanctioned persons
-and that transactions with such persons would be a violation of U.S. export
-controls and sanctions law.
diff --git a/RELEASE.md b/RELEASE.md
index abb79a32a8c..c5aa5d540b1 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -98,6 +98,7 @@ Alternatively use the Github UI.
### Miscellaneous Clean up
+1. Pin the spl-token-cli version in the newly promoted stable branch by setting `splTokenCliVersion` in scripts/spl-token-cli-version.sh to the latest release that depends on the stable branch (usually this will be the latest spl-token-cli release).
1. Update [mergify.yml](https://github.com/solana-labs/solana/blob/master/.mergify.yml) to add backport actions for the new branch and remove actions for the obsolete branch.
1. Adjust the [Github backport labels](https://github.com/solana-labs/solana/labels) to add the new branch label and remove the label for the obsolete branch.
1. Announce on Discord #development that the release branch exists so people know to use the new backport labels.
diff --git a/account-decoder/Cargo.toml b/account-decoder/Cargo.toml
index 3f883ddc23f..7aee8478b4f 100644
--- a/account-decoder/Cargo.toml
+++ b/account-decoder/Cargo.toml
@@ -23,6 +23,7 @@ solana-config-program = { workspace = true }
solana-sdk = { workspace = true }
spl-token = { workspace = true, features = ["no-entrypoint"] }
spl-token-2022 = { workspace = true, features = ["no-entrypoint"] }
+spl-token-group-interface = { workspace = true }
spl-token-metadata-interface = { workspace = true }
thiserror = { workspace = true }
zstd = { workspace = true }
diff --git a/account-decoder/src/parse_token_extension.rs b/account-decoder/src/parse_token_extension.rs
index 39d26d83a20..a2fdef41b47 100644
--- a/account-decoder/src/parse_token_extension.rs
+++ b/account-decoder/src/parse_token_extension.rs
@@ -6,6 +6,7 @@ use {
solana_program::pubkey::Pubkey,
solana_zk_token_sdk::zk_token_elgamal::pod::ElGamalPubkey,
},
+ spl_token_group_interface::state::{TokenGroup, TokenGroupMember},
spl_token_metadata_interface::state::TokenMetadata,
};
@@ -32,6 +33,10 @@ pub enum UiExtension {
TransferHookAccount(UiTransferHookAccount),
MetadataPointer(UiMetadataPointer),
TokenMetadata(UiTokenMetadata),
+ GroupPointer(UiGroupPointer),
+ GroupMemberPointer(UiGroupMemberPointer),
+ TokenGroup(UiTokenGroup),
+ TokenGroupMember(UiTokenGroupMember),
UnparseableExtension,
}
@@ -108,6 +113,22 @@ pub fn parse_extension(
.get_extension::()
.map(|&extension| UiExtension::TransferHookAccount(extension.into()))
.unwrap_or(UiExtension::UnparseableExtension),
+ ExtensionType::GroupPointer => account
+ .get_extension::()
+ .map(|&extension| UiExtension::GroupPointer(extension.into()))
+ .unwrap_or(UiExtension::UnparseableExtension),
+ ExtensionType::GroupMemberPointer => account
+ .get_extension::()
+ .map(|&extension| UiExtension::GroupMemberPointer(extension.into()))
+ .unwrap_or(UiExtension::UnparseableExtension),
+ ExtensionType::TokenGroup => account
+ .get_extension::()
+ .map(|&extension| UiExtension::TokenGroup(extension.into()))
+ .unwrap_or(UiExtension::UnparseableExtension),
+ ExtensionType::TokenGroupMember => account
+ .get_extension::()
+ .map(|&extension| UiExtension::TokenGroupMember(extension.into()))
+ .unwrap_or(UiExtension::UnparseableExtension),
}
}
@@ -481,3 +502,78 @@ impl From for UiTransferHookAccou
}
}
}
+
+#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+#[serde(rename_all = "camelCase")]
+pub struct UiGroupPointer {
+ pub authority: Option,
+ pub group_address: Option,
+}
+
+impl From for UiGroupPointer {
+ fn from(group_pointer: extension::group_pointer::GroupPointer) -> Self {
+ let authority: Option = group_pointer.authority.into();
+ let group_address: Option = group_pointer.group_address.into();
+ Self {
+ authority: authority.map(|pubkey| pubkey.to_string()),
+ group_address: group_address.map(|pubkey| pubkey.to_string()),
+ }
+ }
+}
+
+#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+#[serde(rename_all = "camelCase")]
+pub struct UiGroupMemberPointer {
+ pub authority: Option,
+ pub member_address: Option,
+}
+
+impl From for UiGroupMemberPointer {
+ fn from(member_pointer: extension::group_member_pointer::GroupMemberPointer) -> Self {
+ let authority: Option = member_pointer.authority.into();
+ let member_address: Option = member_pointer.member_address.into();
+ Self {
+ authority: authority.map(|pubkey| pubkey.to_string()),
+ member_address: member_address.map(|pubkey| pubkey.to_string()),
+ }
+ }
+}
+
+#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+#[serde(rename_all = "camelCase")]
+pub struct UiTokenGroup {
+ pub update_authority: Option,
+ pub mint: String,
+ pub size: u32,
+ pub max_size: u32,
+}
+
+impl From for UiTokenGroup {
+ fn from(token_group: TokenGroup) -> Self {
+ let update_authority: Option = token_group.update_authority.into();
+ Self {
+ update_authority: update_authority.map(|pubkey| pubkey.to_string()),
+ mint: token_group.mint.to_string(),
+ size: token_group.size.into(),
+ max_size: token_group.max_size.into(),
+ }
+ }
+}
+
+#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+#[serde(rename_all = "camelCase")]
+pub struct UiTokenGroupMember {
+ pub mint: String,
+ pub group: String,
+ pub member_number: u32,
+}
+
+impl From for UiTokenGroupMember {
+ fn from(member: TokenGroupMember) -> Self {
+ Self {
+ mint: member.mint.to_string(),
+ group: member.group.to_string(),
+ member_number: member.member_number.into(),
+ }
+ }
+}
diff --git a/accounts-cluster-bench/src/main.rs b/accounts-cluster-bench/src/main.rs
index 9e592131a16..2135e9ee19c 100644
--- a/accounts-cluster-bench/src/main.rs
+++ b/accounts-cluster-bench/src/main.rs
@@ -486,7 +486,7 @@ fn run_accounts_bench(
}
fn main() {
- solana_logger::setup_with_default("solana=info");
+ solana_logger::setup_with_default_filter();
let matches = App::new(crate_name!())
.about(crate_description!())
.version(solana_version::version!())
diff --git a/accounts-db/src/accounts_db.rs b/accounts-db/src/accounts_db.rs
index dad1f152f36..9dece549903 100644
--- a/accounts-db/src/accounts_db.rs
+++ b/accounts-db/src/accounts_db.rs
@@ -4395,11 +4395,12 @@ impl AccountsDb {
/// get a sorted list of slots older than an epoch
/// squash those slots into ancient append vecs
- fn shrink_ancient_slots(&self, oldest_non_ancient_slot: Slot) {
+ pub fn shrink_ancient_slots(&self, epoch_schedule: &EpochSchedule) {
if self.ancient_append_vec_offset.is_none() {
return;
}
+ let oldest_non_ancient_slot = self.get_oldest_non_ancient_slot(epoch_schedule);
let can_randomly_shrink = true;
let sorted_slots = self.get_sorted_potential_ancient_slots(oldest_non_ancient_slot);
if self.create_ancient_storage == CreateAncientStorage::Append {
@@ -4744,10 +4745,6 @@ impl AccountsDb {
pub fn shrink_candidate_slots(&self, epoch_schedule: &EpochSchedule) -> usize {
let oldest_non_ancient_slot = self.get_oldest_non_ancient_slot(epoch_schedule);
- if !self.shrink_candidate_slots.lock().unwrap().is_empty() {
- // this can affect 'shrink_candidate_slots', so don't 'take' it until after this completes
- self.shrink_ancient_slots(oldest_non_ancient_slot);
- }
let shrink_candidates_slots =
std::mem::take(&mut *self.shrink_candidate_slots.lock().unwrap());
@@ -7514,6 +7511,11 @@ impl AccountsDb {
self.accounts_hashes.lock().unwrap().get(&slot).cloned()
}
+ /// Get all accounts hashes
+ pub fn get_accounts_hashes(&self) -> HashMap {
+ self.accounts_hashes.lock().unwrap().clone()
+ }
+
/// Set the incremental accounts hash for `slot`
///
/// returns the previous incremental accounts hash for `slot`
@@ -7550,6 +7552,13 @@ impl AccountsDb {
.cloned()
}
+ /// Get all incremental accounts hashes
+ pub fn get_incremental_accounts_hashes(
+ &self,
+ ) -> HashMap {
+ self.incremental_accounts_hashes.lock().unwrap().clone()
+ }
+
/// Purge accounts hashes that are older than `last_full_snapshot_slot`
///
/// Should only be called by AccountsHashVerifier, since it consumes the accounts hashes and
@@ -7640,6 +7649,7 @@ impl AccountsDb {
config: &CalcAccountsHashConfig<'_>,
kind: CalcAccountsHashKind,
slot: Slot,
+ storages_start_slot: Slot,
) -> CacheHashData {
let accounts_hash_cache_path = if !config.store_detailed_debug_info_on_failure {
accounts_hash_cache_path
@@ -7651,7 +7661,10 @@ impl AccountsDb {
_ = std::fs::remove_dir_all(&failed_dir);
failed_dir
};
- CacheHashData::new(accounts_hash_cache_path, kind == CalcAccountsHashKind::Full)
+ CacheHashData::new(
+ accounts_hash_cache_path,
+ (kind == CalcAccountsHashKind::Incremental).then_some(storages_start_slot),
+ )
}
// modeled after calculate_accounts_delta_hash
@@ -7710,7 +7723,8 @@ impl AccountsDb {
) -> Result<(AccountsHashKind, u64), AccountsHashVerificationError> {
let total_time = Measure::start("");
let _guard = self.active_stats.activate(ActiveStatItem::Hash);
- stats.oldest_root = storages.range().start;
+ let storages_start_slot = storages.range().start;
+ stats.oldest_root = storages_start_slot;
self.mark_old_slots_as_dirty(storages, config.epoch_schedule.slots_per_epoch, &mut stats);
@@ -7726,7 +7740,8 @@ impl AccountsDb {
accounts_hash_cache_path,
config,
kind,
- slot
+ slot,
+ storages_start_slot,
));
stats.cache_hash_data_us += cache_hash_data_us;
@@ -9966,7 +9981,7 @@ pub mod tests {
let temp_dir = TempDir::new().unwrap();
let accounts_hash_cache_path = temp_dir.path().to_path_buf();
self.scan_snapshot_stores_with_cache(
- &CacheHashData::new(accounts_hash_cache_path, true),
+ &CacheHashData::new(accounts_hash_cache_path, None),
storage,
stats,
bins,
@@ -11086,7 +11101,7 @@ pub mod tests {
};
let result = accounts_db.scan_account_storage_no_bank(
- &CacheHashData::new(accounts_hash_cache_path, true),
+ &CacheHashData::new(accounts_hash_cache_path, None),
&CalcAccountsHashConfig::default(),
&get_storage_refs(&[storage]),
test_scan,
diff --git a/accounts-db/src/accounts_hash.rs b/accounts-db/src/accounts_hash.rs
index 66a77c81883..ff832cb5612 100644
--- a/accounts-db/src/accounts_hash.rs
+++ b/accounts-db/src/accounts_hash.rs
@@ -26,6 +26,7 @@ use {
atomic::{AtomicU64, AtomicUsize, Ordering},
Arc,
},
+ thread, time,
},
tempfile::tempfile_in,
};
@@ -87,21 +88,59 @@ impl AccountHashesFile {
if self.writer.is_none() {
// we have hashes to write but no file yet, so create a file that will auto-delete on drop
- let mut data = tempfile_in(&self.dir_for_temp_cache_files).unwrap_or_else(|err| {
- panic!(
- "Unable to create file within {}: {err}",
- self.dir_for_temp_cache_files.display()
- )
- });
+ let get_file = || -> Result<_, std::io::Error> {
+ let mut data = tempfile_in(&self.dir_for_temp_cache_files).unwrap_or_else(|err| {
+ panic!(
+ "Unable to create file within {}: {err}",
+ self.dir_for_temp_cache_files.display()
+ )
+ });
+
+ // Theoretical performance optimization: write a zero to the end of
+ // the file so that we won't have to resize it later, which may be
+ // expensive.
+ assert!(self.capacity > 0);
+ data.seek(SeekFrom::Start((self.capacity - 1) as u64))?;
+ data.write_all(&[0])?;
+ data.rewind()?;
+ data.flush()?;
+ Ok(data)
+ };
+
+ // Retry 5 times to allocate the AccountHashesFile. The memory might be fragmented and
+ // causes memory allocation failure. Therefore, let's retry after failure. Hoping that the
+ // kernel has the chance to defrag the memory between the retries, and retries succeed.
+ let mut num_retries = 0;
+ let data = loop {
+ num_retries += 1;
+
+ match get_file() {
+ Ok(data) => {
+ break data;
+ }
+ Err(err) => {
+ info!(
+ "Unable to create account hashes file within {}: {}, retry counter {}",
+ self.dir_for_temp_cache_files.display(),
+ err,
+ num_retries
+ );
- // Theoretical performance optimization: write a zero to the end of
- // the file so that we won't have to resize it later, which may be
- // expensive.
- data.seek(SeekFrom::Start((self.capacity - 1) as u64))
- .unwrap();
- data.write_all(&[0]).unwrap();
- data.rewind().unwrap();
- data.flush().unwrap();
+ if num_retries > 5 {
+ panic!(
+ "Unable to create account hashes file within {}: after {} retries",
+ self.dir_for_temp_cache_files.display(),
+ num_retries
+ );
+ }
+ datapoint_info!(
+ "retry_account_hashes_file_allocation",
+ ("retry", num_retries, i64)
+ );
+ thread::sleep(time::Duration::from_millis(num_retries * 100));
+ }
+ }
+ };
//UNSAFE: Required to create a Mmap
let map = unsafe { MmapMut::map_mut(&data) };
diff --git a/accounts-db/src/cache_hash_data.rs b/accounts-db/src/cache_hash_data.rs
index 630d650b36f..ce5ff5f3aa6 100644
--- a/accounts-db/src/cache_hash_data.rs
+++ b/accounts-db/src/cache_hash_data.rs
@@ -6,6 +6,7 @@ use {
bytemuck::{Pod, Zeroable},
memmap2::MmapMut,
solana_measure::measure::Measure,
+ solana_sdk::clock::Slot,
std::{
collections::HashSet,
fs::{self, remove_file, File, OpenOptions},
@@ -192,24 +193,20 @@ impl CacheHashDataFile {
pub(crate) struct CacheHashData {
cache_dir: PathBuf,
pre_existing_cache_files: Arc>>,
- should_delete_old_cache_files_on_drop: bool,
+ /// Decides which old cache files to delete. See `delete_old_cache_files()` for more info.
+ storages_start_slot: Option,
pub stats: Arc,
}
impl Drop for CacheHashData {
fn drop(&mut self) {
- if self.should_delete_old_cache_files_on_drop {
- self.delete_old_cache_files();
- }
+ self.delete_old_cache_files();
self.stats.report();
}
}
impl CacheHashData {
- pub(crate) fn new(
- cache_dir: PathBuf,
- should_delete_old_cache_files_on_drop: bool,
- ) -> CacheHashData {
+ pub(crate) fn new(cache_dir: PathBuf, storages_start_slot: Option) -> CacheHashData {
std::fs::create_dir_all(&cache_dir).unwrap_or_else(|err| {
panic!("error creating cache dir {}: {err}", cache_dir.display())
});
@@ -217,15 +214,38 @@ impl CacheHashData {
let result = CacheHashData {
cache_dir,
pre_existing_cache_files: Arc::new(Mutex::new(HashSet::default())),
- should_delete_old_cache_files_on_drop,
+ storages_start_slot,
stats: Arc::default(),
};
result.get_cache_files();
result
}
+
+ /// delete all pre-existing files that will not be used
fn delete_old_cache_files(&self) {
- let old_cache_files = std::mem::take(&mut *self.pre_existing_cache_files.lock().unwrap());
+ // all the renaming files in `pre_existing_cache_files` were *not* used for this
+ // accounts hash calculation
+ let mut old_cache_files =
+ std::mem::take(&mut *self.pre_existing_cache_files.lock().unwrap());
+
+ // If `storages_start_slot` is None, we're doing a full accounts hash calculation, and thus
+ // all unused cache files can be deleted.
+ // If `storages_start_slot` is Some, we're doing an incremental accounts hash calculation,
+ // and we only want to delete the unused cache files *that IAH considered*.
+ if let Some(storages_start_slot) = self.storages_start_slot {
+ old_cache_files.retain(|old_cache_file| {
+ let Some(parsed_filename) = parse_filename(old_cache_file) else {
+ // if parsing the cache filename fails, we *do* want to delete it
+ return true;
+ };
+
+ // if the old cache file is in the incremental accounts hash calculation range,
+ // then delete it
+ parsed_filename.slot_range_start >= storages_start_slot
+ });
+ }
+
if !old_cache_files.is_empty() {
self.stats
.unused_cache_files
@@ -356,6 +376,39 @@ impl CacheHashData {
}
}
+/// The values of each part of a cache hash data filename
+#[derive(Debug)]
+pub struct ParsedFilename {
+ pub slot_range_start: Slot,
+ pub slot_range_end: Slot,
+ pub bin_range_start: u64,
+ pub bin_range_end: u64,
+ pub hash: u64,
+}
+
+/// Parses a cache hash data filename into its parts
+///
+/// Returns None if the filename is invalid
+fn parse_filename(cache_filename: impl AsRef) -> Option {
+ let filename = cache_filename.as_ref().to_string_lossy().to_string();
+ let parts: Vec<_> = filename.split('.').collect(); // The parts are separated by a `.`
+ if parts.len() != 5 {
+ return None;
+ }
+ let slot_range_start = parts.first()?.parse().ok()?;
+ let slot_range_end = parts.get(1)?.parse().ok()?;
+ let bin_range_start = parts.get(2)?.parse().ok()?;
+ let bin_range_end = parts.get(3)?.parse().ok()?;
+ let hash = u64::from_str_radix(parts.get(4)?, 16).ok()?; // the hash is in hex
+ Some(ParsedFilename {
+ slot_range_start,
+ slot_range_end,
+ bin_range_start,
+ bin_range_end,
+ hash,
+ })
+}
+
#[cfg(test)]
mod tests {
use {super::*, rand::Rng};
@@ -423,7 +476,7 @@ mod tests {
data_this_pass.push(this_bin_data);
}
}
- let cache = CacheHashData::new(cache_dir.clone(), true);
+ let cache = CacheHashData::new(cache_dir.clone(), None);
let file_name = PathBuf::from("test");
cache.save(&file_name, &data_this_pass).unwrap();
cache.get_cache_files();
@@ -513,4 +566,39 @@ mod tests {
ct,
)
}
+
+ #[test]
+ fn test_parse_filename() {
+ let good_filename = "123.456.0.65536.537d65697d9b2baa";
+ let parsed_filename = parse_filename(good_filename).unwrap();
+ assert_eq!(parsed_filename.slot_range_start, 123);
+ assert_eq!(parsed_filename.slot_range_end, 456);
+ assert_eq!(parsed_filename.bin_range_start, 0);
+ assert_eq!(parsed_filename.bin_range_end, 65536);
+ assert_eq!(parsed_filename.hash, 0x537d65697d9b2baa);
+
+ let bad_filenames = [
+ // bad separator
+ "123-456-0-65536.537d65697d9b2baa",
+ // bad values
+ "abc.456.0.65536.537d65697d9b2baa",
+ "123.xyz.0.65536.537d65697d9b2baa",
+ "123.456.?.65536.537d65697d9b2baa",
+ "123.456.0.@#$%^.537d65697d9b2baa",
+ "123.456.0.65536.base19shouldfail",
+ "123.456.0.65536.123456789012345678901234567890",
+ // missing values
+ "123.456.0.65536.",
+ "123.456.0.65536",
+ // extra junk
+ "123.456.0.65536.537d65697d9b2baa.42",
+ "123.456.0.65536.537d65697d9b2baa.",
+ "123.456.0.65536.537d65697d9b2baa/",
+ ".123.456.0.65536.537d65697d9b2baa",
+ "/123.456.0.65536.537d65697d9b2baa",
+ ];
+ for bad_filename in bad_filenames {
+ assert!(parse_filename(bad_filename).is_none());
+ }
+ }
}
diff --git a/accounts-db/src/verify_accounts_hash_in_background.rs b/accounts-db/src/verify_accounts_hash_in_background.rs
index d4676cfe128..f03e4e0482c 100644
--- a/accounts-db/src/verify_accounts_hash_in_background.rs
+++ b/accounts-db/src/verify_accounts_hash_in_background.rs
@@ -67,7 +67,7 @@ impl VerifyAccountsHashInBackground {
}
let result = lock.take().unwrap().join().unwrap();
if !result {
- panic!("initial hash verification failed: {result:?}");
+ panic!("initial background accounts hash verification failed: {result}");
}
// we never have to check again
self.verification_complete();
@@ -139,7 +139,7 @@ pub mod tests {
}
#[test]
- #[should_panic(expected = "initial hash verification failed")]
+ #[should_panic(expected = "initial background accounts hash verification failed")]
fn test_panic() {
let verify = Arc::new(VerifyAccountsHashInBackground::default());
start_thread_and_return(&verify, false, || {});
diff --git a/banking-bench/src/main.rs b/banking-bench/src/main.rs
index bb5149f47c8..524928aee7c 100644
--- a/banking-bench/src/main.rs
+++ b/banking-bench/src/main.rs
@@ -334,7 +334,7 @@ fn main() {
let (replay_vote_sender, _replay_vote_receiver) = unbounded();
let bank0 = Bank::new_for_benches(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank0)));
+ let bank_forks = BankForks::new_rw_arc(bank0);
let mut bank = bank_forks.read().unwrap().working_bank();
// set cost tracker limits to MAX so it will not filter out TXs
diff --git a/banks-client/src/lib.rs b/banks-client/src/lib.rs
index f0c2f17d8c0..61105575e2c 100644
--- a/banks-client/src/lib.rs
+++ b/banks-client/src/lib.rs
@@ -587,7 +587,7 @@ mod tests {
let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::new_for_tests_with_slots(slot, slot),
));
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let bob_pubkey = solana_sdk::pubkey::new_rand();
let mint_pubkey = genesis.mint_keypair.pubkey();
@@ -626,7 +626,7 @@ mod tests {
let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::new_for_tests_with_slots(slot, slot),
));
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let mint_pubkey = &genesis.mint_keypair.pubkey();
let bob_pubkey = solana_sdk::pubkey::new_rand();
diff --git a/bench-tps/src/main.rs b/bench-tps/src/main.rs
index 519612bd423..e9cc2100635 100644
--- a/bench-tps/src/main.rs
+++ b/bench-tps/src/main.rs
@@ -221,7 +221,7 @@ fn create_client(
}
fn main() {
- solana_logger::setup_with_default("solana=info");
+ solana_logger::setup_with_default_filter();
solana_metrics::set_panic_hook("bench-tps", /*version:*/ None);
let matches = cli::build_args(solana_version::version!()).get_matches();
diff --git a/bench-tps/src/send_batch.rs b/bench-tps/src/send_batch.rs
index b6f1fe776ff..5ea916530ca 100644
--- a/bench-tps/src/send_batch.rs
+++ b/bench-tps/src/send_batch.rs
@@ -248,9 +248,13 @@ where
fn send(&self, client: &Arc) {
let mut send_txs = Measure::start("send_and_clone_txs");
let batch: Vec<_> = self.iter().map(|(_keypair, tx)| tx.clone()).collect();
- client.send_batch(batch).expect("transfer");
+ let result = client.send_batch(batch);
send_txs.stop();
- debug!("send {} {}", self.len(), send_txs);
+ if result.is_err() {
+ debug!("Failed to send batch {result:?}");
+ } else {
+ debug!("send {} {}", self.len(), send_txs);
+ }
}
fn verify(
diff --git a/ci/buildkite-pipeline-in-disk.sh b/ci/buildkite-pipeline-in-disk.sh
index c9816e30a6d..7ca00d7f72e 100755
--- a/ci/buildkite-pipeline-in-disk.sh
+++ b/ci/buildkite-pipeline-in-disk.sh
@@ -196,33 +196,6 @@ EOF
"Stable-SBF skipped as no relevant files were modified"
fi
- # Perf test suite
- if affects \
- .rs$ \
- Cargo.lock$ \
- Cargo.toml$ \
- ^ci/rust-version.sh \
- ^ci/test-stable-perf.sh \
- ^ci/test-stable.sh \
- ^ci/test-local-cluster.sh \
- ^core/build.rs \
- ^fetch-perf-libs.sh \
- ^programs/ \
- ^sdk/ \
- ; then
- cat >> "$output_file" <<"EOF"
- - command: "ci/test-stable-perf.sh"
- name: "stable-perf"
- timeout_in_minutes: 35
- artifact_paths: "log-*.txt"
- agents:
- queue: "cuda"
-EOF
- else
- annotate --style info \
- "Stable-perf skipped as no relevant files were modified"
- fi
-
# Downstream backwards compatibility
if affects \
.rs$ \
@@ -316,7 +289,7 @@ if [[ -n $BUILDKITE_TAG ]]; then
start_pipeline "Tag pipeline for $BUILDKITE_TAG"
annotate --style info --context release-tag \
- "https://github.com/solana-labs/solana/releases/$BUILDKITE_TAG"
+ "https://github.com/anza-xyz/agave/releases/$BUILDKITE_TAG"
# Jump directly to the secondary build to publish release artifacts quickly
trigger_secondary_step
@@ -334,7 +307,7 @@ if [[ $BUILDKITE_BRANCH =~ ^pull ]]; then
# Add helpful link back to the corresponding Github Pull Request
annotate --style info --context pr-backlink \
- "Github Pull Request: https://github.com/solana-labs/solana/$BUILDKITE_BRANCH"
+ "Github Pull Request: https://github.com/anza-xyz/agave/$BUILDKITE_BRANCH"
if [[ $GITHUB_USER = "dependabot[bot]" ]]; then
command_step dependabot "ci/dependabot-pr.sh" 5
diff --git a/ci/buildkite-pipeline.sh b/ci/buildkite-pipeline.sh
index e130c585ad6..68c0c6252f7 100755
--- a/ci/buildkite-pipeline.sh
+++ b/ci/buildkite-pipeline.sh
@@ -121,8 +121,8 @@ EOF
trigger_secondary_step() {
cat >> "$output_file" <<"EOF"
- - name: "Trigger Build on solana-secondary"
- trigger: "solana-secondary"
+ - name: "Trigger Build on agave-secondary"
+ trigger: "agave-secondary"
branches: "!pull/*"
async: true
soft_fail: true
@@ -194,33 +194,6 @@ EOF
"Stable-SBF skipped as no relevant files were modified"
fi
- # Perf test suite
- if affects \
- .rs$ \
- Cargo.lock$ \
- Cargo.toml$ \
- ^ci/rust-version.sh \
- ^ci/test-stable-perf.sh \
- ^ci/test-stable.sh \
- ^ci/test-local-cluster.sh \
- ^core/build.rs \
- ^fetch-perf-libs.sh \
- ^programs/ \
- ^sdk/ \
- ; then
- cat >> "$output_file" <<"EOF"
- - command: "ci/test-stable-perf.sh"
- name: "stable-perf"
- timeout_in_minutes: 35
- artifact_paths: "log-*.txt"
- agents:
- queue: "cuda"
-EOF
- else
- annotate --style info \
- "Stable-perf skipped as no relevant files were modified"
- fi
-
# Downstream backwards compatibility
if affects \
.rs$ \
@@ -340,7 +313,7 @@ if [[ -n $BUILDKITE_TAG ]]; then
start_pipeline "Tag pipeline for $BUILDKITE_TAG"
annotate --style info --context release-tag \
- "https://github.com/solana-labs/solana/releases/$BUILDKITE_TAG"
+ "https://github.com/anza-xyz/agave/releases/$BUILDKITE_TAG"
# Jump directly to the secondary build to publish release artifacts quickly
trigger_secondary_step
@@ -358,7 +331,7 @@ if [[ $BUILDKITE_BRANCH =~ ^pull ]]; then
# Add helpful link back to the corresponding Github Pull Request
annotate --style info --context pr-backlink \
- "Github Pull Request: https://github.com/solana-labs/solana/$BUILDKITE_BRANCH"
+ "Github Pull Request: https://github.com/anza-xyz/agave/$BUILDKITE_BRANCH"
if [[ $GITHUB_USER = "dependabot[bot]" ]]; then
command_step dependabot "ci/dependabot-pr.sh" 5
diff --git a/ci/buildkite-solana-private.sh b/ci/buildkite-solana-private.sh
index 57a3d3de3b2..a2366d5701c 100755
--- a/ci/buildkite-solana-private.sh
+++ b/ci/buildkite-solana-private.sh
@@ -180,33 +180,6 @@ EOF
"Stable-SBF skipped as no relevant files were modified"
fi
- # Perf test suite
- if affects \
- .rs$ \
- Cargo.lock$ \
- Cargo.toml$ \
- ^ci/rust-version.sh \
- ^ci/test-stable-perf.sh \
- ^ci/test-stable.sh \
- ^ci/test-local-cluster.sh \
- ^core/build.rs \
- ^fetch-perf-libs.sh \
- ^programs/ \
- ^sdk/ \
- ; then
- cat >> "$output_file" <<"EOF"
- - command: "ci/test-stable-perf.sh"
- name: "stable-perf"
- timeout_in_minutes: 35
- artifact_paths: "log-*.txt"
- agents:
- queue: "sol-private"
-EOF
- else
- annotate --style info \
- "Stable-perf skipped as no relevant files were modified"
- fi
-
# Downstream backwards compatibility
if affects \
.rs$ \
@@ -314,7 +287,7 @@ if [[ $BUILDKITE_BRANCH =~ ^pull ]]; then
# Add helpful link back to the corresponding Github Pull Request
annotate --style info --context pr-backlink \
- "Github Pull Request: https://github.com/solana-labs/solana/$BUILDKITE_BRANCH"
+ "Github Pull Request: https://github.com/anza-xyz/agave/$BUILDKITE_BRANCH"
if [[ $GITHUB_USER = "dependabot[bot]" ]]; then
command_step dependabot "ci/dependabot-pr.sh" 5
diff --git a/ci/channel-info.sh b/ci/channel-info.sh
index c82806454d0..2bb80836565 100755
--- a/ci/channel-info.sh
+++ b/ci/channel-info.sh
@@ -11,7 +11,7 @@ here="$(dirname "$0")"
# shellcheck source=ci/semver_bash/semver.sh
source "$here"/semver_bash/semver.sh
-remote=https://github.com/solana-labs/solana.git
+remote=https://github.com/anza-xyz/agave.git
# Fetch all vX.Y.Z tags
#
diff --git a/ci/check-install-all.sh b/ci/check-install-all.sh
new file mode 100755
index 00000000000..0ffb52a3708
--- /dev/null
+++ b/ci/check-install-all.sh
@@ -0,0 +1,5 @@
+source scripts/spl-token-cli-version.sh
+if [[ -z $splTokenCliVersion ]]; then
+ echo "On the stable channel, splTokenCliVersion must be set in scripts/spl-token-cli-version.sh"
+ exit 1
+fi
diff --git a/ci/dependabot-pr.sh b/ci/dependabot-pr.sh
index 9ef6816cec5..8638a7d5257 100755
--- a/ci/dependabot-pr.sh
+++ b/ci/dependabot-pr.sh
@@ -21,7 +21,7 @@ fi
echo --- "(FAILING) Backpropagating dependabot-triggered Cargo.lock updates"
name="dependabot-buildkite"
-api_base="https://api.github.com/repos/solana-labs/solana/pulls"
+api_base="https://api.github.com/repos/anza-xyz/agave/pulls"
pr_num=$(echo "$BUILDKITE_BRANCH" | grep -Eo '[0-9]+')
branch=$(curl -s "$api_base/$pr_num" | python3 -c 'import json,sys;print(json.load(sys.stdin)["head"]["ref"])')
diff --git a/ci/do-audit.sh b/ci/do-audit.sh
index 039df6b63cb..0118c84c5f0 100755
--- a/ci/do-audit.sh
+++ b/ci/do-audit.sh
@@ -30,6 +30,9 @@ cargo_audit_ignores=(
--ignore RUSTSEC-2023-0001
--ignore RUSTSEC-2022-0093
+
+ # mio
+ --ignore RUSTSEC-2024-0019
)
scripts/cargo-for-all-lock-files.sh audit "${cargo_audit_ignores[@]}" | $dep_tree_filter
# we want the `cargo audit` exit code, not `$dep_tree_filter`'s
diff --git a/ci/docker-run.sh b/ci/docker-run.sh
index eb9d06836f6..aa39a3c844e 100755
--- a/ci/docker-run.sh
+++ b/ci/docker-run.sh
@@ -54,16 +54,34 @@ if [[ -n $CI ]]; then
# sccache-related bugs
echo "--- $0 ... (with sccache being DISABLED due to many (${BUILDKITE_RETRY_COUNT}) retries)"
else
- echo "--- $0 ... (with sccache enabled with prefix: $SCCACHE_S3_KEY_PREFIX)"
+ echo "--- $0 ... (with sccache enabled with prefix: $SCCACHE_KEY_PREFIX)"
+
# sccache
ARGS+=(
--env "RUSTC_WRAPPER=/usr/local/cargo/bin/sccache"
- --env AWS_ACCESS_KEY_ID
- --env AWS_SECRET_ACCESS_KEY
- --env SCCACHE_BUCKET
- --env SCCACHE_REGION
- --env SCCACHE_S3_KEY_PREFIX
)
+
+ # s3
+ if [ -n "$AWS_ACCESS_KEY_ID" ]; then
+ ARGS+=(
+ --env AWS_ACCESS_KEY_ID
+ --env AWS_SECRET_ACCESS_KEY
+ --env SCCACHE_BUCKET
+ --env SCCACHE_REGION
+ --env SCCACHE_S3_KEY_PREFIX
+ )
+ fi
+
+ # gcs
+ if [ -n "$SCCACHE_GCS_KEY_PATH" ]; then
+ ARGS+=(
+ --env SCCACHE_GCS_KEY_PATH
+ --volume "$SCCACHE_GCS_KEY_PATH:$SCCACHE_GCS_KEY_PATH"
+ --env SCCACHE_GCS_BUCKET
+ --env SCCACHE_GCS_RW_MODE
+ --env SCCACHE_GCS_KEY_PREFIX
+ )
+ fi
fi
fi
else
diff --git a/ci/docker-rust-nightly/Dockerfile b/ci/docker-rust-nightly/Dockerfile
index 23262061e4f..a5d933b2a2d 100644
--- a/ci/docker-rust-nightly/Dockerfile
+++ b/ci/docker-rust-nightly/Dockerfile
@@ -1,4 +1,4 @@
-FROM solanalabs/rust:1.72.1
+FROM solanalabs/rust:1.73.0
ARG date
RUN set -x \
diff --git a/ci/docker-rust/Dockerfile b/ci/docker-rust/Dockerfile
index e5d80f9e04b..8dfc347d54d 100644
--- a/ci/docker-rust/Dockerfile
+++ b/ci/docker-rust/Dockerfile
@@ -1,6 +1,6 @@
# Note: when the rust version is changed also modify
# ci/rust-version.sh to pick up the new image tag
-FROM rust:1.72.1
+FROM rust:1.73.0
ARG NODE_MAJOR=18
diff --git a/ci/localnet-sanity.sh b/ci/localnet-sanity.sh
index e6734e180aa..b01eca31d50 100755
--- a/ci/localnet-sanity.sh
+++ b/ci/localnet-sanity.sh
@@ -202,8 +202,8 @@ killNodes() {
# Try to use the RPC exit API to cleanly exit the first two nodes
# (dynamic nodes, -x, are just killed)
echo "--- RPC exit"
- $solana_validator --ledger "$SOLANA_CONFIG_DIR"/bootstrap-validator exit --force || true
- $solana_validator --ledger "$SOLANA_CONFIG_DIR"/validator exit --force || true
+ $agave_validator --ledger "$SOLANA_CONFIG_DIR"/bootstrap-validator exit --force || true
+ $agave_validator --ledger "$SOLANA_CONFIG_DIR"/validator exit --force || true
# Give the nodes a splash of time to cleanly exit before killing them
sleep 2
diff --git a/ci/publish-crate.sh b/ci/publish-crate.sh
index fb13ec1d53d..099d02129e3 100755
--- a/ci/publish-crate.sh
+++ b/ci/publish-crate.sh
@@ -63,37 +63,27 @@ for Cargo_toml in $Cargo_tomls; do
(
set -x
+
crate=$(dirname "$Cargo_toml")
- # The rocksdb package does not build with the stock rust docker image so use
- # the solana rust docker image
cargoCommand="cargo publish --token $CRATES_IO_TOKEN"
- ci/docker-run.sh "$rust_stable_docker_image" bash -exc "cd $crate; $cargoCommand"
- ) || true # <-- Don't fail. We want to be able to retry the job in cases when a publish fails halfway due to network/cloud issues
-
- numRetries=30
- for ((i = 1 ; i <= numRetries ; i++)); do
- echo "Attempt ${i} of ${numRetries}"
- if [[ $(is_crate_version_uploaded "$crate_name" "$expectedCrateVersion") = True ]] ; then
- echo "Found ${crate_name} version ${expectedCrateVersion} on crates.io REST API"
-
- really_uploaded=0
- (
- set -x
- rm -rf crate-test
- cargo init crate-test
- cd crate-test/
- echo "${crate_name} = \"=${expectedCrateVersion}\"" >> Cargo.toml
- echo "[workspace]" >> Cargo.toml
- cargo check
- ) && really_uploaded=1
- if ((really_uploaded)); then
- break;
+
+ numRetries=10
+ for ((i = 1; i <= numRetries; i++)); do
+ echo "Attempt ${i} of ${numRetries}"
+ # The rocksdb package does not build with the stock rust docker image so use
+ # the solana rust docker image
+ if ci/docker-run.sh "$rust_stable_docker_image" bash -exc "cd $crate; $cargoCommand"; then
+ break
+ fi
+
+ if [ "$i" -lt "$numRetries" ]; then
+ sleep 3
+ else
+ echo "couldn't publish '$crate_name'"
+ exit 1
fi
- echo "${crate_name} not yet available for download from crates.io"
- fi
- echo "Did not find ${crate_name} version ${expectedCrateVersion} on crates.io. Sleeping for 2 seconds."
- sleep 2
- done
+ done
+ )
done
exit 0
diff --git a/ci/publish-installer.sh b/ci/publish-installer.sh
index 4b5345ae0d2..f7d98ffd5dd 100755
--- a/ci/publish-installer.sh
+++ b/ci/publish-installer.sh
@@ -26,14 +26,14 @@ fi
# upload install script
source ci/upload-ci-artifact.sh
-cat >release.solana.com-install <release.anza.xyz-install <>release.solana.com-install
+cat install/agave-install-init.sh >>release.anza.xyz-install
-echo --- AWS S3 Store: "install"
-upload-s3-artifact "/solana/release.solana.com-install" "s3://release.solana.com/$CHANNEL_OR_TAG/install"
+echo --- GCS: "install"
+upload-gcs-artifact "/solana/release.anza.xyz-install" "gs://anza-release/$CHANNEL_OR_TAG/install"
echo Published to:
-ci/format-url.sh https://release.solana.com/"$CHANNEL_OR_TAG"/install
+ci/format-url.sh https://release.anza.xyz/"$CHANNEL_OR_TAG"/install
diff --git a/ci/publish-tarball.sh b/ci/publish-tarball.sh
index ff72bb7da2d..da5862fb3de 100755
--- a/ci/publish-tarball.sh
+++ b/ci/publish-tarball.sh
@@ -93,7 +93,7 @@ echo --- Creating release tarball
tar cvf "${TARBALL_BASENAME}"-$TARGET.tar "${RELEASE_BASENAME}"
bzip2 "${TARBALL_BASENAME}"-$TARGET.tar
- cp "${RELEASE_BASENAME}"/bin/solana-install-init solana-install-init-$TARGET
+ cp "${RELEASE_BASENAME}"/bin/agave-install-init agave-install-init-$TARGET
cp "${RELEASE_BASENAME}"/version.yml "${TARBALL_BASENAME}"-$TARGET.yml
)
@@ -110,7 +110,7 @@ fi
source ci/upload-ci-artifact.sh
-for file in "${TARBALL_BASENAME}"-$TARGET.tar.bz2 "${TARBALL_BASENAME}"-$TARGET.yml solana-install-init-"$TARGET"* $MAYBE_TARBALLS; do
+for file in "${TARBALL_BASENAME}"-$TARGET.tar.bz2 "${TARBALL_BASENAME}"-$TARGET.yml agave-install-init-"$TARGET"* $MAYBE_TARBALLS; do
if [[ -n $DO_NOT_PUBLISH_TAR ]]; then
upload-ci-artifact "$file"
echo "Skipped $file due to DO_NOT_PUBLISH_TAR"
@@ -118,11 +118,11 @@ for file in "${TARBALL_BASENAME}"-$TARGET.tar.bz2 "${TARBALL_BASENAME}"-$TARGET.
fi
if [[ -n $BUILDKITE ]]; then
- echo --- AWS S3 Store: "$file"
- upload-s3-artifact "/solana/$file" s3://release.solana.com/"$CHANNEL_OR_TAG"/"$file"
+ echo --- GCS Store: "$file"
+ upload-gcs-artifact "/solana/$file" gs://anza-release/"$CHANNEL_OR_TAG"/"$file"
echo Published to:
- $DRYRUN ci/format-url.sh https://release.solana.com/"$CHANNEL_OR_TAG"/"$file"
+ $DRYRUN ci/format-url.sh https://release.anza.xyz/"$CHANNEL_OR_TAG"/"$file"
if [[ -n $TAG ]]; then
ci/upload-github-release-asset.sh "$file"
diff --git a/ci/run-sanity.sh b/ci/run-sanity.sh
index 3e674d92f4e..d9527def4e2 100755
--- a/ci/run-sanity.sh
+++ b/ci/run-sanity.sh
@@ -31,7 +31,7 @@ while [[ $latest_slot -le $((snapshot_slot + 1)) ]]; do
latest_slot=$($solana_cli --url http://localhost:8899 slot --commitment processed)
done
-$solana_validator --ledger config/ledger exit --force || true
+$agave_validator --ledger config/ledger exit --force || true
wait $pid
diff --git a/ci/rust-version.sh b/ci/rust-version.sh
index 76f929277ba..a38910accda 100644
--- a/ci/rust-version.sh
+++ b/ci/rust-version.sh
@@ -29,7 +29,7 @@ fi
if [[ -n $RUST_NIGHTLY_VERSION ]]; then
nightly_version="$RUST_NIGHTLY_VERSION"
else
- nightly_version=2023-09-20
+ nightly_version=2023-10-05
fi
diff --git a/ci/test-checks.sh b/ci/test-checks.sh
index 0f037cb3478..533d05e1720 100755
--- a/ci/test-checks.sh
+++ b/ci/test-checks.sh
@@ -61,35 +61,7 @@ fi
_ ci/order-crates-for-publishing.py
-nightly_clippy_allows=(--allow=clippy::redundant_clone)
-
-# Use nightly clippy, as frozen-abi proc-macro generates a lot of code across
-# various crates in this whole monorepo (frozen-abi is enabled only under nightly
-# due to the use of unstable rust feature). Likewise, frozen-abi(-macro) crates'
-# unit tests are only compiled under nightly.
-# Similarly, nightly is desired to run clippy over all of bench files because
-# the bench itself isn't stabilized yet...
-# ref: https://github.com/rust-lang/rust/issues/66287
-_ scripts/cargo-for-all-lock-files.sh -- "+${rust_nightly}" clippy --workspace --all-targets --features dummy-for-ci-check -- \
- --deny=warnings \
- --deny=clippy::default_trait_access \
- --deny=clippy::arithmetic_side_effects \
- --deny=clippy::manual_let_else \
- --deny=clippy::used_underscore_binding \
- "${nightly_clippy_allows[@]}"
-
-# temporarily run stable clippy as well to scan the codebase for
-# `redundant_clone`s, which is disabled as nightly clippy is buggy:
-# https://github.com/solana-labs/solana/issues/31834
-#
-# can't use --all-targets:
-# error[E0554]: `#![feature]` may not be used on the stable release channel
-_ scripts/cargo-for-all-lock-files.sh -- clippy --workspace --tests --bins --examples --features dummy-for-ci-check -- \
- --deny=warnings \
- --deny=clippy::default_trait_access \
- --deny=clippy::arithmetic_side_effects \
- --deny=clippy::manual_let_else \
- --deny=clippy::used_underscore_binding
+_ scripts/cargo-clippy.sh
if [[ -n $CI ]]; then
# exclude from printing "Checking xxx ..."
@@ -104,4 +76,8 @@ _ scripts/cargo-for-all-lock-files.sh -- "+${rust_nightly}" fmt --all -- --check
_ ci/do-audit.sh
+if [[ -n $CI ]] && [[ $CHANNEL = "stable" ]]; then
+ _ ci/check-install-all.sh
+fi
+
echo --- ok
diff --git a/ci/test-coverage.sh b/ci/test-coverage.sh
index 44231cd338a..ffd362acd28 100755
--- a/ci/test-coverage.sh
+++ b/ci/test-coverage.sh
@@ -32,5 +32,5 @@ else
codecov -t "${CODECOV_TOKEN}"
annotate --style success --context codecov.io \
- "CodeCov report: https://codecov.io/github/solana-labs/solana/commit/${CI_COMMIT:0:9}"
+ "CodeCov report: https://codecov.io/github/anza-xyz/agave/commit/${CI_COMMIT:0:9}"
fi
diff --git a/ci/upload-ci-artifact.sh b/ci/upload-ci-artifact.sh
index 1236da9f271..e7cc34ab2b2 100644
--- a/ci/upload-ci-artifact.sh
+++ b/ci/upload-ci-artifact.sh
@@ -40,3 +40,13 @@ upload-s3-artifact() {
docker run "${args[@]}"
)
}
+
+upload-gcs-artifact() {
+ echo "--- artifact: $1 to $2"
+ docker run --rm \
+ -v "$GCS_RELEASE_BUCKET_WRITER_CREDIENTIAL:/application_default_credentials.json" \
+ -v "$PWD:/solana" \
+ -e CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE=/application_default_credentials.json \
+ gcr.io/google.com/cloudsdktool/google-cloud-cli:latest \
+ gcloud storage cp "$1" "$2"
+}
diff --git a/ci/upload-github-release-asset.sh b/ci/upload-github-release-asset.sh
index ca2ae2a8f60..229fb8993ed 100755
--- a/ci/upload-github-release-asset.sh
+++ b/ci/upload-github-release-asset.sh
@@ -26,7 +26,7 @@ fi
# Force CI_REPO_SLUG since sometimes
# BUILDKITE_TRIGGERED_FROM_BUILD_PIPELINE_SLUG is not set correctly, causing the
# artifact upload to fail
-CI_REPO_SLUG=solana-labs/solana
+CI_REPO_SLUG=anza-xyz/agave
#if [[ -z $CI_REPO_SLUG ]]; then
# echo Error: CI_REPO_SLUG not defined
# exit 1
diff --git a/cli/src/cluster_query.rs b/cli/src/cluster_query.rs
index 0470cf761ad..ee683081ed4 100644
--- a/cli/src/cluster_query.rs
+++ b/cli/src/cluster_query.rs
@@ -1886,23 +1886,17 @@ pub fn process_show_validators(
progress_bar.set_message("Fetching block production...");
let skip_rate: HashMap<_, _> = rpc_client
- .get_block_production()
- .ok()
- .map(|result| {
- result
- .value
- .by_identity
- .into_iter()
- .map(|(identity, (leader_slots, blocks_produced))| {
- (
- identity,
- 100. * (leader_slots.saturating_sub(blocks_produced)) as f64
- / leader_slots as f64,
- )
- })
- .collect()
+ .get_block_production()?
+ .value
+ .by_identity
+ .into_iter()
+ .map(|(identity, (leader_slots, blocks_produced))| {
+ (
+ identity,
+ 100. * (leader_slots.saturating_sub(blocks_produced)) as f64 / leader_slots as f64,
+ )
})
- .unwrap_or_default();
+ .collect();
progress_bar.set_message("Fetching version information...");
let mut node_version = HashMap::new();
diff --git a/cli/src/feature.rs b/cli/src/feature.rs
index 8c065d78fee..f4fc225aa0f 100644
--- a/cli/src/feature.rs
+++ b/cli/src/feature.rs
@@ -850,8 +850,7 @@ fn process_status(
let mut features = vec![];
for feature_ids in feature_ids.chunks(MAX_MULTIPLE_ACCOUNTS) {
let mut feature_chunk = rpc_client
- .get_multiple_accounts(feature_ids)
- .unwrap_or_default()
+ .get_multiple_accounts(feature_ids)?
.into_iter()
.zip(feature_ids)
.map(|(account, feature_id)| {
diff --git a/cli/src/stake.rs b/cli/src/stake.rs
index 96c1b50b357..337b2843ff2 100644
--- a/cli/src/stake.rs
+++ b/cli/src/stake.rs
@@ -710,7 +710,7 @@ impl StakeSubCommands for App<'_, '_> {
Arg::with_name("csv")
.long("csv")
.takes_value(false)
- .help("Format stake account data in csv")
+ .help("Format stake rewards data in csv")
)
.arg(
Arg::with_name("num_rewards_epochs")
diff --git a/client-test/tests/client.rs b/client-test/tests/client.rs
index 65acd1adaae..71db9e0f5e6 100644
--- a/client-test/tests/client.rs
+++ b/client-test/tests/client.rs
@@ -132,7 +132,7 @@ fn test_account_subscription() {
} = create_genesis_config(10_000);
let bank = Bank::new_for_tests(&genesis_config);
let blockhash = bank.last_blockhash();
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let bank0 = bank_forks.read().unwrap().get(0).unwrap();
let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
bank_forks.write().unwrap().insert(bank1);
@@ -168,7 +168,7 @@ fn test_account_subscription() {
// Transfer 100 lamports from alice to bob
let tx = system_transaction::transfer(&alice, &bob.pubkey(), 100, blockhash);
bank_forks
- .write()
+ .read()
.unwrap()
.get(1)
.unwrap()
@@ -230,7 +230,7 @@ fn test_block_subscription() {
} = create_genesis_config(10_000);
let bank = Bank::new_for_tests(&genesis_config);
let rent_exempt_amount = bank.get_minimum_balance_for_rent_exemption(0);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
// setup Blockstore
let ledger_path = get_tmp_ledger_path!();
@@ -338,7 +338,7 @@ fn test_program_subscription() {
} = create_genesis_config(10_000);
let bank = Bank::new_for_tests(&genesis_config);
let blockhash = bank.last_blockhash();
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let bank0 = bank_forks.read().unwrap().get(0).unwrap();
let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
bank_forks.write().unwrap().insert(bank1);
@@ -373,7 +373,7 @@ fn test_program_subscription() {
// Create new program account at bob's address
let tx = system_transaction::create_account(&alice, &bob, blockhash, 100, 0, &program_id);
bank_forks
- .write()
+ .read()
.unwrap()
.get(1)
.unwrap()
@@ -425,7 +425,7 @@ fn test_root_subscription() {
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
let bank = Bank::new_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let bank0 = bank_forks.read().unwrap().get(0).unwrap();
let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
bank_forks.write().unwrap().insert(bank1);
@@ -477,7 +477,7 @@ fn test_slot_subscription() {
let exit = Arc::new(AtomicBool::new(false));
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
let bank = Bank::new_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let optimistically_confirmed_bank =
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
@@ -553,7 +553,7 @@ async fn test_slot_subscription_async() {
let exit = Arc::new(AtomicBool::new(false));
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
let bank = Bank::new_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let optimistically_confirmed_bank =
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
diff --git a/core/benches/banking_stage.rs b/core/benches/banking_stage.rs
index 2526c2a6369..b399abba0a9 100644
--- a/core/benches/banking_stage.rs
+++ b/core/benches/banking_stage.rs
@@ -55,7 +55,7 @@ use {
},
std::{
iter::repeat_with,
- sync::{atomic::Ordering, Arc, RwLock},
+ sync::{atomic::Ordering, Arc},
time::{Duration, Instant},
},
test::Bencher,
@@ -219,7 +219,7 @@ fn bench_banking(bencher: &mut Bencher, tx_type: TransactionType) {
let mut bank = Bank::new_for_benches(&genesis_config);
// Allow arbitrary transaction processing time for the purposes of this bench
bank.ns_per_slot = u128::MAX;
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let bank = bank_forks.read().unwrap().get(0).unwrap();
// set cost tracker limits to MAX so it will not filter out TXs
diff --git a/core/benches/consensus.rs b/core/benches/consensus.rs
index a3dd97755e9..cff71502df9 100644
--- a/core/benches/consensus.rs
+++ b/core/benches/consensus.rs
@@ -28,7 +28,10 @@ fn bench_save_tower(bench: &mut Bencher) {
let vote_account_pubkey = &Pubkey::default();
let node_keypair = Arc::new(Keypair::new());
- let heaviest_bank = BankForks::new(Bank::default_for_tests()).working_bank();
+ let heaviest_bank = BankForks::new_rw_arc(Bank::default_for_tests())
+ .read()
+ .unwrap()
+ .working_bank();
let tower_storage = FileTowerStorage::new(dir.path().to_path_buf());
let tower = Tower::new(
&node_keypair.pubkey(),
@@ -47,7 +50,10 @@ fn bench_save_tower(bench: &mut Bencher) {
fn bench_generate_ancestors_descendants(bench: &mut Bencher) {
let vote_account_pubkey = &Pubkey::default();
let node_keypair = Arc::new(Keypair::new());
- let heaviest_bank = BankForks::new(Bank::default_for_tests()).working_bank();
+ let heaviest_bank = BankForks::new_rw_arc(Bank::default_for_tests())
+ .read()
+ .unwrap()
+ .working_bank();
let mut tower = Tower::new(
&node_keypair.pubkey(),
vote_account_pubkey,
diff --git a/core/src/accounts_hash_verifier.rs b/core/src/accounts_hash_verifier.rs
index cb87cdc513a..1d7e5ae7fb5 100644
--- a/core/src/accounts_hash_verifier.rs
+++ b/core/src/accounts_hash_verifier.rs
@@ -104,12 +104,21 @@ impl AccountsHashVerifier {
));
if let Some(snapshot_storages_for_fastboot) = snapshot_storages_for_fastboot {
- let num_storages = snapshot_storages_for_fastboot.len();
+ // Get the number of storages that are being kept alive for fastboot.
+ // Looking at the storage Arc's strong reference count, we know that one
+ // ref is for fastboot, and one ref is for snapshot packaging. If there
+ // are no others, then the storage will be kept alive because of fastboot.
+ let num_storages_kept_alive = snapshot_storages_for_fastboot
+ .iter()
+ .filter(|storage| Arc::strong_count(storage) == 2)
+ .count();
+ let num_storages_total = snapshot_storages_for_fastboot.len();
fastboot_storages = Some(snapshot_storages_for_fastboot);
datapoint_info!(
"fastboot",
("slot", slot, i64),
- ("num_storages", num_storages, i64),
+ ("num_storages_total", num_storages_total, i64),
+ ("num_storages_kept_alive", num_storages_kept_alive, i64),
);
}
@@ -312,11 +321,26 @@ impl AccountsHashVerifier {
else {
panic!("Calculating incremental accounts hash requires a base slot");
};
- let (base_accounts_hash, base_capitalization) = accounts_package
- .accounts
- .accounts_db
- .get_accounts_hash(base_slot)
- .expect("incremental snapshot requires accounts hash and capitalization from the full snapshot it is based on");
+ let accounts_db = &accounts_package.accounts.accounts_db;
+ let Some((base_accounts_hash, base_capitalization)) =
+ accounts_db.get_accounts_hash(base_slot)
+ else {
+ panic!(
+ "incremental snapshot requires accounts hash and capitalization \
+ from the full snapshot it is based on \n\
+ package: {accounts_package:?} \n\
+ accounts hashes: {:?} \n\
+ incremental accounts hashes: {:?} \n\
+ full snapshot archives: {:?} \n\
+ bank snapshots: {:?}",
+ accounts_db.get_accounts_hashes(),
+ accounts_db.get_incremental_accounts_hashes(),
+ snapshot_utils::get_full_snapshot_archives(
+ &snapshot_config.full_snapshot_archives_dir,
+ ),
+ snapshot_utils::get_bank_snapshots(&snapshot_config.bank_snapshots_dir),
+ );
+ };
let (incremental_accounts_hash, incremental_capitalization) =
Self::_calculate_incremental_accounts_hash(accounts_package, base_slot);
let bank_incremental_snapshot_persistence = BankIncrementalSnapshotPersistence {
diff --git a/core/src/banking_stage.rs b/core/src/banking_stage.rs
index e8b61de94dc..ad52db88ac4 100644
--- a/core/src/banking_stage.rs
+++ b/core/src/banking_stage.rs
@@ -670,7 +670,7 @@ mod tests {
fn test_banking_stage_shutdown1() {
let genesis_config = create_genesis_config(2).genesis_config;
let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let bank = bank_forks.read().unwrap().get(0).unwrap();
let banking_tracer = BankingTracer::new_disabled();
let (non_vote_sender, non_vote_receiver) = banking_tracer.create_channel_non_vote();
@@ -722,7 +722,7 @@ mod tests {
genesis_config.ticks_per_slot = 4;
let num_extra_ticks = 2;
let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let bank = bank_forks.read().unwrap().get(0).unwrap();
let start_hash = bank.last_blockhash();
let banking_tracer = BankingTracer::new_disabled();
@@ -802,7 +802,7 @@ mod tests {
..
} = create_slow_genesis_config(10);
let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let bank = bank_forks.read().unwrap().get(0).unwrap();
let start_hash = bank.last_blockhash();
let banking_tracer = BankingTracer::new_disabled();
@@ -974,7 +974,7 @@ mod tests {
let entry_receiver = {
// start a banking_stage to eat verified receiver
let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let bank = bank_forks.read().unwrap().get(0).unwrap();
let blockstore = Arc::new(
Blockstore::open(ledger_path.path())
@@ -1155,7 +1155,7 @@ mod tests {
..
} = create_slow_genesis_config(10000);
let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let bank = bank_forks.read().unwrap().get(0).unwrap();
let start_hash = bank.last_blockhash();
let banking_tracer = BankingTracer::new_disabled();
diff --git a/core/src/banking_stage/committer.rs b/core/src/banking_stage/committer.rs
index a5e42cbc75f..88b129aae3d 100644
--- a/core/src/banking_stage/committer.rs
+++ b/core/src/banking_stage/committer.rs
@@ -15,7 +15,7 @@ use {
prioritization_fee_cache::PrioritizationFeeCache,
transaction_batch::TransactionBatch,
},
- solana_sdk::{pubkey::Pubkey, saturating_add_assign},
+ solana_sdk::{hash::Hash, pubkey::Pubkey, saturating_add_assign},
solana_transaction_status::{
token_balances::TransactionTokenBalancesSet, TransactionTokenBalance,
},
@@ -65,6 +65,8 @@ impl Committer {
batch: &TransactionBatch,
loaded_transactions: &mut [TransactionLoadResult],
execution_results: Vec,
+ last_blockhash: Hash,
+ lamports_per_signature: u64,
starting_transaction_index: Option,
bank: &Arc,
pre_balance_info: &mut PreBalanceInfo,
@@ -74,9 +76,6 @@ impl Committer {
executed_non_vote_transactions_count: usize,
executed_with_successful_result_count: usize,
) -> (u64, Vec) {
- let (last_blockhash, lamports_per_signature) =
- bank.last_blockhash_and_lamports_per_signature();
-
let executed_transactions = execution_results
.iter()
.zip(batch.sanitized_transactions())
diff --git a/core/src/banking_stage/consume_worker.rs b/core/src/banking_stage/consume_worker.rs
index 1795db97439..d2451efa1c4 100644
--- a/core/src/banking_stage/consume_worker.rs
+++ b/core/src/banking_stage/consume_worker.rs
@@ -174,7 +174,7 @@ mod tests {
..
} = create_slow_genesis_config(10_000);
let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let bank = bank_forks.read().unwrap().working_bank();
let ledger_path = get_tmp_ledger_path_auto_delete!();
diff --git a/core/src/banking_stage/consumer.rs b/core/src/banking_stage/consumer.rs
index ba915bc767e..c8624a96aad 100644
--- a/core/src/banking_stage/consumer.rs
+++ b/core/src/banking_stage/consumer.rs
@@ -554,7 +554,8 @@ impl Consumer {
transaction_status_sender_enabled,
&mut execute_and_commit_timings.execute_timings,
None, // account_overrides
- self.log_messages_bytes_limit
+ self.log_messages_bytes_limit,
+ true,
));
execute_and_commit_timings.load_execute_us = load_execute_us;
@@ -587,6 +588,10 @@ impl Consumer {
let (freeze_lock, freeze_lock_us) = measure_us!(bank.freeze_lock());
execute_and_commit_timings.freeze_lock_us = freeze_lock_us;
+ let ((last_blockhash, lamports_per_signature), last_blockhash_us) =
+ measure_us!(bank.last_blockhash_and_lamports_per_signature());
+ execute_and_commit_timings.last_blockhash_us = last_blockhash_us;
+
let (record_transactions_summary, record_us) = measure_us!(self
.transaction_recorder
.record_transactions(bank.slot(), executed_transactions));
@@ -623,6 +628,8 @@ impl Consumer {
batch,
&mut loaded_transactions,
execution_results,
+ last_blockhash,
+ lamports_per_signature,
starting_transaction_index,
bank,
&mut pre_balance_info,
diff --git a/core/src/banking_stage/forward_worker.rs b/core/src/banking_stage/forward_worker.rs
index cabd891e761..c13b8c42637 100644
--- a/core/src/banking_stage/forward_worker.rs
+++ b/core/src/banking_stage/forward_worker.rs
@@ -129,7 +129,7 @@ mod tests {
..
} = create_slow_genesis_config(10_000);
let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let bank = bank_forks.read().unwrap().working_bank();
let ledger_path = get_tmp_ledger_path_auto_delete!();
diff --git a/core/src/banking_stage/forwarder.rs b/core/src/banking_stage/forwarder.rs
index 777ea12d95b..1cb656f0ddc 100644
--- a/core/src/banking_stage/forwarder.rs
+++ b/core/src/banking_stage/forwarder.rs
@@ -307,7 +307,7 @@ mod tests {
let GenesisConfigInfo { genesis_config, .. } = &genesis_config_info;
let bank: Bank = Bank::new_no_wallclock_throttle_for_tests(genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let bank = bank_forks.read().unwrap().working_bank();
let ledger_path = TempDir::new().unwrap();
diff --git a/core/src/banking_stage/immutable_deserialized_packet.rs b/core/src/banking_stage/immutable_deserialized_packet.rs
index 4617702059b..0fd6a3f16e1 100644
--- a/core/src/banking_stage/immutable_deserialized_packet.rs
+++ b/core/src/banking_stage/immutable_deserialized_packet.rs
@@ -1,4 +1,5 @@
use {
+ solana_cost_model::block_cost_limits::BUILT_IN_INSTRUCTION_COSTS,
solana_perf::packet::Packet,
solana_runtime::transaction_priority_details::{
GetTransactionPriorityDetails, TransactionPriorityDetails,
@@ -8,6 +9,7 @@ use {
hash::Hash,
message::Message,
sanitize::SanitizeError,
+ saturating_add_assign,
short_vec::decode_shortu16_len,
signature::Signature,
transaction::{
@@ -96,6 +98,22 @@ impl ImmutableDeserializedPacket {
self.priority_details.compute_unit_limit
}
+ /// Returns true if the transaction's compute unit limit is at least as
+ /// large as the sum of the static builtins' costs.
+ /// This is a simple sanity check so the leader can discard transactions
+ /// which are statically known to exceed the compute budget, and will
+ /// result in no useful state-change.
+ pub fn compute_unit_limit_above_static_builtins(&self) -> bool {
+ let mut static_builtin_cost_sum: u64 = 0;
+ for (program_id, _) in self.transaction.get_message().program_instructions_iter() {
+ if let Some(ix_cost) = BUILT_IN_INSTRUCTION_COSTS.get(program_id) {
+ saturating_add_assign!(static_builtin_cost_sum, *ix_cost);
+ }
+ }
+
+ self.compute_unit_limit() >= static_builtin_cost_sum
+ }
+
// This function deserializes packets into transactions, computes the blake3 hash of transaction
// messages, and verifies secp256k1 instructions.
pub fn build_sanitized_transaction(
@@ -148,7 +166,10 @@ fn packet_message(packet: &Packet) -> Result<&[u8], DeserializedPacketError> {
mod tests {
use {
super::*,
- solana_sdk::{signature::Keypair, system_transaction},
+ solana_sdk::{
+ compute_budget, instruction::Instruction, pubkey::Pubkey, signature::Keypair,
+ signer::Signer, system_instruction, system_transaction, transaction::Transaction,
+ },
};
#[test]
@@ -164,4 +185,33 @@ mod tests {
assert!(deserialized_packet.is_ok());
}
+
+ #[test]
+ fn compute_unit_limit_above_static_builtins() {
+ // Cases:
+ // 1. compute_unit_limit under static builtins
+ // 2. compute_unit_limit equal to static builtins
+ // 3. compute_unit_limit above static builtins
+ for (cu_limit, expectation) in [(250, false), (300, true), (350, true)] {
+ let keypair = Keypair::new();
+ let bpf_program_id = Pubkey::new_unique();
+ let ixs = vec![
+ system_instruction::transfer(&keypair.pubkey(), &Pubkey::new_unique(), 1),
+ compute_budget::ComputeBudgetInstruction::set_compute_unit_limit(cu_limit),
+ Instruction::new_with_bytes(bpf_program_id, &[], vec![]), // non-builtin - not counted in filter
+ ];
+ let tx = Transaction::new_signed_with_payer(
+ &ixs,
+ Some(&keypair.pubkey()),
+ &[&keypair],
+ Hash::new_unique(),
+ );
+ let packet = Packet::from_data(None, tx).unwrap();
+ let deserialized_packet = ImmutableDeserializedPacket::new(packet).unwrap();
+ assert_eq!(
+ deserialized_packet.compute_unit_limit_above_static_builtins(),
+ expectation
+ );
+ }
+ }
}
diff --git a/core/src/banking_stage/leader_slot_timing_metrics.rs b/core/src/banking_stage/leader_slot_timing_metrics.rs
index 543b80b4a48..7727b6cf6c6 100644
--- a/core/src/banking_stage/leader_slot_timing_metrics.rs
+++ b/core/src/banking_stage/leader_slot_timing_metrics.rs
@@ -10,6 +10,7 @@ pub struct LeaderExecuteAndCommitTimings {
pub collect_balances_us: u64,
pub load_execute_us: u64,
pub freeze_lock_us: u64,
+ pub last_blockhash_us: u64,
pub record_us: u64,
pub commit_us: u64,
pub find_and_send_votes_us: u64,
@@ -22,6 +23,7 @@ impl LeaderExecuteAndCommitTimings {
saturating_add_assign!(self.collect_balances_us, other.collect_balances_us);
saturating_add_assign!(self.load_execute_us, other.load_execute_us);
saturating_add_assign!(self.freeze_lock_us, other.freeze_lock_us);
+ saturating_add_assign!(self.last_blockhash_us, other.last_blockhash_us);
saturating_add_assign!(self.record_us, other.record_us);
saturating_add_assign!(self.commit_us, other.commit_us);
saturating_add_assign!(self.find_and_send_votes_us, other.find_and_send_votes_us);
@@ -38,6 +40,7 @@ impl LeaderExecuteAndCommitTimings {
("collect_balances_us", self.collect_balances_us as i64, i64),
("load_execute_us", self.load_execute_us as i64, i64),
("freeze_lock_us", self.freeze_lock_us as i64, i64),
+ ("last_blockhash_us", self.last_blockhash_us as i64, i64),
("record_us", self.record_us as i64, i64),
("commit_us", self.commit_us as i64, i64),
(
diff --git a/core/src/banking_stage/packet_deserializer.rs b/core/src/banking_stage/packet_deserializer.rs
index a405b626568..1d1079eaf97 100644
--- a/core/src/banking_stage/packet_deserializer.rs
+++ b/core/src/banking_stage/packet_deserializer.rs
@@ -50,6 +50,7 @@ impl PacketDeserializer {
&self,
recv_timeout: Duration,
capacity: usize,
+ packet_filter: impl Fn(&ImmutableDeserializedPacket) -> bool,
) -> Result {
let (packet_count, packet_batches) = self.receive_until(recv_timeout, capacity)?;
@@ -62,6 +63,7 @@ impl PacketDeserializer {
packet_count,
&packet_batches,
round_compute_unit_price_enabled,
+ &packet_filter,
))
}
@@ -71,6 +73,7 @@ impl PacketDeserializer {
packet_count: usize,
banking_batches: &[BankingPacketBatch],
round_compute_unit_price_enabled: bool,
+ packet_filter: &impl Fn(&ImmutableDeserializedPacket) -> bool,
) -> ReceivePacketResults {
let mut passed_sigverify_count: usize = 0;
let mut failed_sigverify_count: usize = 0;
@@ -88,6 +91,7 @@ impl PacketDeserializer {
packet_batch,
&packet_indexes,
round_compute_unit_price_enabled,
+ packet_filter,
));
}
@@ -158,13 +162,16 @@ impl PacketDeserializer {
packet_batch: &'a PacketBatch,
packet_indexes: &'a [usize],
round_compute_unit_price_enabled: bool,
+ packet_filter: &'a (impl Fn(&ImmutableDeserializedPacket) -> bool + 'a),
) -> impl Iterator- + 'a {
packet_indexes.iter().filter_map(move |packet_index| {
let mut packet_clone = packet_batch[*packet_index].clone();
packet_clone
.meta_mut()
.set_round_compute_unit_price(round_compute_unit_price_enabled);
- ImmutableDeserializedPacket::new(packet_clone).ok()
+ ImmutableDeserializedPacket::new(packet_clone)
+ .ok()
+ .filter(packet_filter)
})
}
}
@@ -186,7 +193,7 @@ mod tests {
#[test]
fn test_deserialize_and_collect_packets_empty() {
- let results = PacketDeserializer::deserialize_and_collect_packets(0, &[], false);
+ let results = PacketDeserializer::deserialize_and_collect_packets(0, &[], false, &|_| true);
assert_eq!(results.deserialized_packets.len(), 0);
assert!(results.new_tracer_stats_option.is_none());
assert_eq!(results.passed_sigverify_count, 0);
@@ -204,6 +211,7 @@ mod tests {
packet_count,
&[BankingPacketBatch::new((packet_batches, None))],
false,
+ &|_| true,
);
assert_eq!(results.deserialized_packets.len(), 2);
assert!(results.new_tracer_stats_option.is_none());
@@ -223,6 +231,7 @@ mod tests {
packet_count,
&[BankingPacketBatch::new((packet_batches, None))],
false,
+ &|_| true,
);
assert_eq!(results.deserialized_packets.len(), 1);
assert!(results.new_tracer_stats_option.is_none());
diff --git a/core/src/banking_stage/packet_receiver.rs b/core/src/banking_stage/packet_receiver.rs
index a566ef7cf3e..bbb753967f2 100644
--- a/core/src/banking_stage/packet_receiver.rs
+++ b/core/src/banking_stage/packet_receiver.rs
@@ -49,6 +49,7 @@ impl PacketReceiver {
.receive_packets(
recv_timeout,
unprocessed_transaction_storage.max_receive_size(),
+ |packet| packet.compute_unit_limit_above_static_builtins(),
)
// Consumes results if Ok, otherwise we keep the Err
.map(|receive_packet_results| {
diff --git a/core/src/banking_trace.rs b/core/src/banking_trace.rs
index 760121dc7c5..ba76b794ba2 100644
--- a/core/src/banking_trace.rs
+++ b/core/src/banking_trace.rs
@@ -62,16 +62,17 @@ pub struct BankingTracer {
active_tracer: Option,
}
-#[derive(Serialize, Deserialize, Debug)]
+#[frozen_abi(digest = "Eq6YrAFtTbtPrCEvh6Et1mZZDCARUg1gcK2qiZdqyjUz")]
+#[derive(Serialize, Deserialize, Debug, AbiExample)]
pub struct TimedTracedEvent(pub std::time::SystemTime, pub TracedEvent);
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Debug, AbiExample, AbiEnumVisitor)]
pub enum TracedEvent {
PacketBatch(ChannelLabel, BankingPacketBatch),
BlockAndBankHash(Slot, Hash, Hash),
}
-#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
+#[derive(Serialize, Deserialize, Debug, Clone, Copy, AbiExample, AbiEnumVisitor)]
pub enum ChannelLabel {
NonVote,
TpuVote,
diff --git a/core/src/cluster_info_vote_listener.rs b/core/src/cluster_info_vote_listener.rs
index 183cabcf04d..782f10d976b 100644
--- a/core/src/cluster_info_vote_listener.rs
+++ b/core/src/cluster_info_vote_listener.rs
@@ -1439,7 +1439,7 @@ mod tests {
);
let bank = Bank::new_for_tests(&genesis_config);
let exit = Arc::new(AtomicBool::new(false));
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let bank = bank_forks.read().unwrap().get(0).unwrap();
let vote_tracker = VoteTracker::default();
let optimistically_confirmed_bank =
@@ -1556,7 +1556,7 @@ mod tests {
let bank = Bank::new_for_tests(&genesis_config);
let vote_tracker = VoteTracker::default();
let exit = Arc::new(AtomicBool::new(false));
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let bank = bank_forks.read().unwrap().get(0).unwrap();
let optimistically_confirmed_bank =
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
@@ -1584,7 +1584,7 @@ mod tests {
solana_logger::setup();
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
let bank = Bank::new_for_tests(&genesis_config);
- let bank_forks = RwLock::new(BankForks::new(bank));
+ let bank_forks = BankForks::new_rw_arc(bank);
let votes = vec![];
let (vote_txs, packets) = ClusterInfoVoteListener::verify_votes(votes, &bank_forks);
assert!(vote_txs.is_empty());
@@ -1629,7 +1629,7 @@ mod tests {
vec![100; voting_keypairs.len()], // stakes
);
let bank = Bank::new_for_tests(&genesis_config);
- let bank_forks = RwLock::new(BankForks::new(bank));
+ let bank_forks = BankForks::new_rw_arc(bank);
let vote_tx = test_vote_tx(voting_keypairs.first(), hash);
let votes = vec![vote_tx];
let (vote_txs, packets) = ClusterInfoVoteListener::verify_votes(votes, &bank_forks);
@@ -1654,7 +1654,7 @@ mod tests {
vec![100; voting_keypairs.len()], // stakes
);
let bank = Bank::new_for_tests(&genesis_config);
- let bank_forks = RwLock::new(BankForks::new(bank));
+ let bank_forks = BankForks::new_rw_arc(bank);
let vote_tx = test_vote_tx(voting_keypairs.first(), hash);
let mut bad_vote = vote_tx.clone();
bad_vote.signatures[0] = Signature::default();
diff --git a/core/src/commitment_service.rs b/core/src/commitment_service.rs
index bdadb1ff72f..84242b44c64 100644
--- a/core/src/commitment_service.rs
+++ b/core/src/commitment_service.rs
@@ -509,12 +509,12 @@ mod tests {
);
let bank0 = Bank::new_for_tests(&genesis_config);
- let mut bank_forks = BankForks::new(bank0);
+ let bank_forks = BankForks::new_rw_arc(bank0);
// Fill bank_forks with banks with votes landing in the next slot
// Create enough banks such that vote account will root slots 0 and 1
for x in 0..33 {
- let previous_bank = bank_forks.get(x).unwrap();
+ let previous_bank = bank_forks.read().unwrap().get(x).unwrap();
let bank = Bank::new_from_parent(previous_bank.clone(), &Pubkey::default(), x + 1);
let vote = vote_transaction::new_vote_transaction(
vec![x],
@@ -526,20 +526,23 @@ mod tests {
None,
);
bank.process_transaction(&vote).unwrap();
- bank_forks.insert(bank);
+ bank_forks.write().unwrap().insert(bank);
}
- let working_bank = bank_forks.working_bank();
+ let working_bank = bank_forks.read().unwrap().working_bank();
let root = get_vote_account_root_slot(
validator_vote_keypairs.vote_keypair.pubkey(),
&working_bank,
);
for x in 0..root {
- bank_forks.set_root(x, &AbsRequestSender::default(), None);
+ bank_forks
+ .write()
+ .unwrap()
+ .set_root(x, &AbsRequestSender::default(), None);
}
// Add an additional bank/vote that will root slot 2
- let bank33 = bank_forks.get(33).unwrap();
+ let bank33 = bank_forks.read().unwrap().get(33).unwrap();
let bank34 = Bank::new_from_parent(bank33.clone(), &Pubkey::default(), 34);
let vote33 = vote_transaction::new_vote_transaction(
vec![33],
@@ -551,9 +554,9 @@ mod tests {
None,
);
bank34.process_transaction(&vote33).unwrap();
- bank_forks.insert(bank34);
+ bank_forks.write().unwrap().insert(bank34);
- let working_bank = bank_forks.working_bank();
+ let working_bank = bank_forks.read().unwrap().working_bank();
let root = get_vote_account_root_slot(
validator_vote_keypairs.vote_keypair.pubkey(),
&working_bank,
@@ -572,21 +575,22 @@ mod tests {
.read()
.unwrap()
.highest_super_majority_root();
- bank_forks.set_root(
+ bank_forks.write().unwrap().set_root(
root,
&AbsRequestSender::default(),
Some(highest_super_majority_root),
);
- let highest_super_majority_root_bank = bank_forks.get(highest_super_majority_root);
+ let highest_super_majority_root_bank =
+ bank_forks.read().unwrap().get(highest_super_majority_root);
assert!(highest_super_majority_root_bank.is_some());
// Add a forked bank. Because the vote for bank 33 landed in the non-ancestor, the vote
// account's root (and thus the highest_super_majority_root) rolls back to slot 1
- let bank33 = bank_forks.get(33).unwrap();
+ let bank33 = bank_forks.read().unwrap().get(33).unwrap();
let bank35 = Bank::new_from_parent(bank33, &Pubkey::default(), 35);
- bank_forks.insert(bank35);
+ bank_forks.write().unwrap().insert(bank35);
- let working_bank = bank_forks.working_bank();
+ let working_bank = bank_forks.read().unwrap().working_bank();
let ancestors = working_bank.status_cache_ancestors();
let _ = AggregateCommitmentService::update_commitment_cache(
&block_commitment_cache,
@@ -601,13 +605,14 @@ mod tests {
.read()
.unwrap()
.highest_super_majority_root();
- let highest_super_majority_root_bank = bank_forks.get(highest_super_majority_root);
+ let highest_super_majority_root_bank =
+ bank_forks.read().unwrap().get(highest_super_majority_root);
assert!(highest_super_majority_root_bank.is_some());
// Add additional banks beyond lockout built on the new fork to ensure that behavior
// continues normally
for x in 35..=37 {
- let previous_bank = bank_forks.get(x).unwrap();
+ let previous_bank = bank_forks.read().unwrap().get(x).unwrap();
let bank = Bank::new_from_parent(previous_bank.clone(), &Pubkey::default(), x + 1);
let vote = vote_transaction::new_vote_transaction(
vec![x],
@@ -619,10 +624,10 @@ mod tests {
None,
);
bank.process_transaction(&vote).unwrap();
- bank_forks.insert(bank);
+ bank_forks.write().unwrap().insert(bank);
}
- let working_bank = bank_forks.working_bank();
+ let working_bank = bank_forks.read().unwrap().working_bank();
let root = get_vote_account_root_slot(
validator_vote_keypairs.vote_keypair.pubkey(),
&working_bank,
@@ -641,12 +646,13 @@ mod tests {
.read()
.unwrap()
.highest_super_majority_root();
- bank_forks.set_root(
+ bank_forks.write().unwrap().set_root(
root,
&AbsRequestSender::default(),
Some(highest_super_majority_root),
);
- let highest_super_majority_root_bank = bank_forks.get(highest_super_majority_root);
+ let highest_super_majority_root_bank =
+ bank_forks.read().unwrap().get(highest_super_majority_root);
assert!(highest_super_majority_root_bank.is_some());
}
}
diff --git a/core/src/consensus.rs b/core/src/consensus.rs
index 675dfc691e6..59c0adf7243 100644
--- a/core/src/consensus.rs
+++ b/core/src/consensus.rs
@@ -279,6 +279,28 @@ impl Tower {
}
}
+ #[cfg(test)]
+ pub fn new_random(node_pubkey: Pubkey) -> Self {
+ use rand::Rng;
+
+ let mut rng = rand::thread_rng();
+ let root_slot = rng.gen();
+ let vote_state = VoteState::new_rand_for_tests(node_pubkey, root_slot);
+ let last_vote = VoteStateUpdate::from(
+ vote_state
+ .votes
+ .iter()
+ .map(|lv| (lv.slot(), lv.confirmation_count()))
+ .collect::>(),
+ );
+ Self {
+ node_pubkey,
+ vote_state,
+ last_vote: VoteTransaction::CompactVoteStateUpdate(last_vote),
+ ..Tower::default()
+ }
+ }
+
pub fn new_from_bankforks(
bank_forks: &BankForks,
node_pubkey: &Pubkey,
@@ -1427,6 +1449,9 @@ impl TowerError {
false
}
}
+ pub fn is_too_old(&self) -> bool {
+ matches!(self, TowerError::TooOldTower(_, _))
+ }
}
#[derive(Debug)]
diff --git a/core/src/consensus/heaviest_subtree_fork_choice.rs b/core/src/consensus/heaviest_subtree_fork_choice.rs
index 639272e1048..4b58ee78b99 100644
--- a/core/src/consensus/heaviest_subtree_fork_choice.rs
+++ b/core/src/consensus/heaviest_subtree_fork_choice.rs
@@ -244,7 +244,8 @@ impl HeaviestSubtreeForkChoice {
heaviest_subtree_fork_choice
}
- pub fn new_from_bank_forks(bank_forks: &BankForks) -> Self {
+ pub fn new_from_bank_forks(bank_forks: Arc>) -> Self {
+ let bank_forks = bank_forks.read().unwrap();
let mut frozen_banks: Vec<_> = bank_forks.frozen_banks().values().cloned().collect();
frozen_banks.sort_by_key(|bank| bank.slot());
diff --git a/core/src/repair/ancestor_hashes_service.rs b/core/src/repair/ancestor_hashes_service.rs
index 3214c89e14e..fc70dbab16c 100644
--- a/core/src/repair/ancestor_hashes_service.rs
+++ b/core/src/repair/ancestor_hashes_service.rs
@@ -1928,7 +1928,7 @@ mod test {
#[test]
fn test_verify_and_process_ancestor_responses_invalid_packet() {
let bank0 = Bank::default_for_tests();
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank0)));
+ let bank_forks = BankForks::new_rw_arc(bank0);
let ManageAncestorHashesState {
ancestor_hashes_request_statuses,
diff --git a/core/src/repair/quic_endpoint.rs b/core/src/repair/quic_endpoint.rs
index f7b445011c9..89f9de78491 100644
--- a/core/src/repair/quic_endpoint.rs
+++ b/core/src/repair/quic_endpoint.rs
@@ -6,31 +6,35 @@ use {
log::error,
quinn::{
ClientConfig, ConnectError, Connecting, Connection, ConnectionError, Endpoint,
- EndpointConfig, ReadToEndError, RecvStream, SendStream, ServerConfig, TokioRuntime,
- TransportConfig, VarInt, WriteError,
+ EndpointConfig, IdleTimeout, ReadError, ReadToEndError, RecvStream, SendStream,
+ ServerConfig, TokioRuntime, TransportConfig, VarInt, WriteError,
},
rcgen::RcgenError,
rustls::{Certificate, PrivateKey},
serde_bytes::ByteBuf,
solana_quic_client::nonblocking::quic_client::SkipServerVerification,
+ solana_runtime::bank_forks::BankForks,
solana_sdk::{packet::PACKET_DATA_SIZE, pubkey::Pubkey, signature::Keypair},
solana_streamer::{
quic::SkipClientVerification, tls_certificates::new_self_signed_tls_certificate,
},
std::{
+ cmp::Reverse,
collections::{hash_map::Entry, HashMap},
io::{Cursor, Error as IoError},
net::{IpAddr, SocketAddr, UdpSocket},
- ops::Deref,
- sync::Arc,
+ sync::{
+ atomic::{AtomicBool, AtomicU64, Ordering},
+ Arc, RwLock,
+ },
time::Duration,
},
thiserror::Error,
tokio::{
sync::{
- mpsc::{Receiver as AsyncReceiver, Sender as AsyncSender},
+ mpsc::{error::TrySendError, Receiver as AsyncReceiver, Sender as AsyncSender},
oneshot::Sender as OneShotSender,
- RwLock,
+ Mutex, RwLock as AsyncRwLock,
},
task::JoinHandle,
},
@@ -39,22 +43,30 @@ use {
const ALPN_REPAIR_PROTOCOL_ID: &[u8] = b"solana-repair";
const CONNECT_SERVER_NAME: &str = "solana-repair";
-const CLIENT_CHANNEL_CAPACITY: usize = 1 << 14;
-const CONNECTION_CACHE_CAPACITY: usize = 4096;
+const CLIENT_CHANNEL_BUFFER: usize = 1 << 14;
+const ROUTER_CHANNEL_BUFFER: usize = 64;
+const CONNECTION_CACHE_CAPACITY: usize = 3072;
+
+// Transport config.
+// Repair randomly samples peers, uses bi-directional streams and generally has
+// low to moderate load and so is configured separately from other protocols.
+const KEEP_ALIVE_INTERVAL: Duration = Duration::from_secs(4);
const MAX_CONCURRENT_BIDI_STREAMS: VarInt = VarInt::from_u32(512);
+const MAX_IDLE_TIMEOUT: Duration = Duration::from_secs(10);
const CONNECTION_CLOSE_ERROR_CODE_SHUTDOWN: VarInt = VarInt::from_u32(1);
const CONNECTION_CLOSE_ERROR_CODE_DROPPED: VarInt = VarInt::from_u32(2);
const CONNECTION_CLOSE_ERROR_CODE_INVALID_IDENTITY: VarInt = VarInt::from_u32(3);
const CONNECTION_CLOSE_ERROR_CODE_REPLACED: VarInt = VarInt::from_u32(4);
+const CONNECTION_CLOSE_ERROR_CODE_PRUNED: VarInt = VarInt::from_u32(5);
const CONNECTION_CLOSE_REASON_SHUTDOWN: &[u8] = b"SHUTDOWN";
const CONNECTION_CLOSE_REASON_DROPPED: &[u8] = b"DROPPED";
const CONNECTION_CLOSE_REASON_INVALID_IDENTITY: &[u8] = b"INVALID_IDENTITY";
const CONNECTION_CLOSE_REASON_REPLACED: &[u8] = b"REPLACED";
+const CONNECTION_CLOSE_REASON_PRUNED: &[u8] = b"PRUNED";
pub(crate) type AsyncTryJoinHandle = TryJoin, JoinHandle<()>>;
-type ConnectionCache = HashMap<(SocketAddr, Option), Arc>>>;
// Outgoing local requests.
pub struct LocalRequest {
@@ -76,16 +88,14 @@ pub struct RemoteRequest {
#[derive(Error, Debug)]
#[allow(clippy::enum_variant_names)]
pub(crate) enum Error {
- #[error(transparent)]
- BincodeError(#[from] bincode::Error),
#[error(transparent)]
CertificateError(#[from] RcgenError),
+ #[error("Channel Send Error")]
+ ChannelSendError,
#[error(transparent)]
ConnectError(#[from] ConnectError),
#[error(transparent)]
ConnectionError(#[from] ConnectionError),
- #[error("Channel Send Error")]
- ChannelSendError,
#[error("Invalid Identity: {0:?}")]
InvalidIdentity(SocketAddr),
#[error(transparent)]
@@ -97,9 +107,15 @@ pub(crate) enum Error {
#[error("read_to_end Timeout")]
ReadToEndTimeout,
#[error(transparent)]
- WriteError(#[from] WriteError),
- #[error(transparent)]
TlsError(#[from] rustls::Error),
+ #[error(transparent)]
+ WriteError(#[from] WriteError),
+}
+
+macro_rules! add_metric {
+ ($metric: expr) => {{
+ $metric.fetch_add(1, Ordering::Relaxed);
+ }};
}
#[allow(clippy::type_complexity)]
@@ -109,6 +125,7 @@ pub(crate) fn new_quic_endpoint(
socket: UdpSocket,
address: IpAddr,
remote_request_sender: Sender,
+ bank_forks: Arc>,
) -> Result<(Endpoint, AsyncSender, AsyncTryJoinHandle), Error> {
let (cert, key) = new_self_signed_tls_certificate(keypair, address)?;
let server_config = new_server_config(cert.clone(), key.clone())?;
@@ -125,17 +142,25 @@ pub(crate) fn new_quic_endpoint(
)?
};
endpoint.set_default_client_config(client_config);
- let cache = Arc::>::default();
- let (client_sender, client_receiver) = tokio::sync::mpsc::channel(CLIENT_CHANNEL_CAPACITY);
+ let prune_cache_pending = Arc::::default();
+ let cache = Arc::>>::default();
+ let (client_sender, client_receiver) = tokio::sync::mpsc::channel(CLIENT_CHANNEL_BUFFER);
+ let router = Arc::>>>::default();
let server_task = runtime.spawn(run_server(
endpoint.clone(),
remote_request_sender.clone(),
+ bank_forks.clone(),
+ prune_cache_pending.clone(),
+ router.clone(),
cache.clone(),
));
let client_task = runtime.spawn(run_client(
endpoint.clone(),
client_receiver,
remote_request_sender,
+ bank_forks,
+ prune_cache_pending,
+ router,
cache,
));
let task = futures::future::try_join(server_task, client_task);
@@ -176,54 +201,135 @@ fn new_client_config(cert: Certificate, key: PrivateKey) -> Result TransportConfig {
+ let max_idle_timeout = IdleTimeout::try_from(MAX_IDLE_TIMEOUT).unwrap();
let mut config = TransportConfig::default();
+ // Disable datagrams and uni streams.
config
+ .datagram_receive_buffer_size(None)
+ .keep_alive_interval(Some(KEEP_ALIVE_INTERVAL))
.max_concurrent_bidi_streams(MAX_CONCURRENT_BIDI_STREAMS)
.max_concurrent_uni_streams(VarInt::from(0u8))
- .datagram_receive_buffer_size(None);
+ .max_idle_timeout(Some(max_idle_timeout));
config
}
async fn run_server(
endpoint: Endpoint,
remote_request_sender: Sender,
- cache: Arc>,
+ bank_forks: Arc>,
+ prune_cache_pending: Arc,
+ router: Arc>>>,
+ cache: Arc>>,
) {
+ let stats = Arc::::default();
+ let report_metrics_task =
+ tokio::task::spawn(report_metrics_task("repair_quic_server", stats.clone()));
while let Some(connecting) = endpoint.accept().await {
- tokio::task::spawn(handle_connecting_error(
+ tokio::task::spawn(handle_connecting_task(
endpoint.clone(),
connecting,
remote_request_sender.clone(),
+ bank_forks.clone(),
+ prune_cache_pending.clone(),
+ router.clone(),
cache.clone(),
+ stats.clone(),
));
}
+ report_metrics_task.abort();
}
async fn run_client(
endpoint: Endpoint,
mut receiver: AsyncReceiver,
remote_request_sender: Sender,
- cache: Arc>,
+ bank_forks: Arc>,
+ prune_cache_pending: Arc,
+ router: Arc>>>,
+ cache: Arc>>,
) {
+ let stats = Arc::::default();
+ let report_metrics_task =
+ tokio::task::spawn(report_metrics_task("repair_quic_client", stats.clone()));
while let Some(request) = receiver.recv().await {
- tokio::task::spawn(send_request_task(
+ let Some(request) = try_route_request(request, &*router.read().await, &stats) else {
+ continue;
+ };
+ let remote_address = request.remote_address;
+ let receiver = {
+ let mut router = router.write().await;
+ let Some(request) = try_route_request(request, &router, &stats) else {
+ continue;
+ };
+ let (sender, receiver) = tokio::sync::mpsc::channel(ROUTER_CHANNEL_BUFFER);
+ sender.try_send(request).unwrap();
+ router.insert(remote_address, sender);
+ receiver
+ };
+ tokio::task::spawn(make_connection_task(
endpoint.clone(),
- request,
+ remote_address,
remote_request_sender.clone(),
+ receiver,
+ bank_forks.clone(),
+ prune_cache_pending.clone(),
+ router.clone(),
cache.clone(),
+ stats.clone(),
));
}
close_quic_endpoint(&endpoint);
+ // Drop sender channels to unblock threads waiting on the receiving end.
+ router.write().await.clear();
+ report_metrics_task.abort();
}
-async fn handle_connecting_error(
+// Routes the local request to respective channel. Drops the request if the
+// channel is full. Bounces the request back if the channel is closed or does
+// not exist.
+fn try_route_request(
+ request: LocalRequest,
+ router: &HashMap>,
+ stats: &RepairQuicStats,
+) -> Option {
+ match router.get(&request.remote_address) {
+ None => Some(request),
+ Some(sender) => match sender.try_send(request) {
+ Ok(()) => None,
+ Err(TrySendError::Full(request)) => {
+ debug!("TrySendError::Full {}", request.remote_address);
+ add_metric!(stats.router_try_send_error_full);
+ None
+ }
+ Err(TrySendError::Closed(request)) => Some(request),
+ },
+ }
+}
+
+async fn handle_connecting_task(
endpoint: Endpoint,
connecting: Connecting,
remote_request_sender: Sender,
- cache: Arc>,
+ bank_forks: Arc>,
+ prune_cache_pending: Arc,
+ router: Arc>>>,
+ cache: Arc>>,
+ stats: Arc,
) {
- if let Err(err) = handle_connecting(endpoint, connecting, remote_request_sender, cache).await {
- error!("handle_connecting: {err:?}");
+ if let Err(err) = handle_connecting(
+ endpoint,
+ connecting,
+ remote_request_sender,
+ bank_forks,
+ prune_cache_pending,
+ router,
+ cache,
+ stats.clone(),
+ )
+ .await
+ {
+ debug!("handle_connecting: {err:?}");
+ record_error(&err, &stats);
}
}
@@ -231,52 +337,103 @@ async fn handle_connecting(
endpoint: Endpoint,
connecting: Connecting,
remote_request_sender: Sender,
- cache: Arc>,
+ bank_forks: Arc>,
+ prune_cache_pending: Arc,
+ router: Arc>>>,
+ cache: Arc>>,
+ stats: Arc,
) -> Result<(), Error> {
let connection = connecting.await?;
let remote_address = connection.remote_address();
let remote_pubkey = get_remote_pubkey(&connection)?;
- handle_connection_error(
+ let receiver = {
+ let (sender, receiver) = tokio::sync::mpsc::channel(ROUTER_CHANNEL_BUFFER);
+ router.write().await.insert(remote_address, sender);
+ receiver
+ };
+ handle_connection(
endpoint,
remote_address,
remote_pubkey,
connection,
remote_request_sender,
+ receiver,
+ bank_forks,
+ prune_cache_pending,
+ router,
cache,
+ stats,
)
.await;
Ok(())
}
-async fn handle_connection_error(
+#[allow(clippy::too_many_arguments)]
+async fn handle_connection(
endpoint: Endpoint,
remote_address: SocketAddr,
remote_pubkey: Pubkey,
connection: Connection,
remote_request_sender: Sender,
- cache: Arc>,
+ receiver: AsyncReceiver,
+ bank_forks: Arc>,
+ prune_cache_pending: Arc,
+ router: Arc>>>,
+ cache: Arc>>,
+ stats: Arc,
) {
- cache_connection(remote_address, remote_pubkey, connection.clone(), &cache).await;
- if let Err(err) = handle_connection(
- &endpoint,
- remote_address,
+ cache_connection(
remote_pubkey,
- &connection,
- &remote_request_sender,
+ connection.clone(),
+ bank_forks,
+ prune_cache_pending,
+ router.clone(),
+ cache.clone(),
)
- .await
- {
- drop_connection(remote_address, remote_pubkey, &connection, &cache).await;
- error!("handle_connection: {remote_pubkey}, {remote_address}, {err:?}");
+ .await;
+ let send_requests_task = tokio::task::spawn(send_requests_task(
+ endpoint.clone(),
+ remote_address,
+ connection.clone(),
+ receiver,
+ stats.clone(),
+ ));
+ let recv_requests_task = tokio::task::spawn(recv_requests_task(
+ endpoint,
+ remote_address,
+ remote_pubkey,
+ connection.clone(),
+ remote_request_sender,
+ stats.clone(),
+ ));
+ match futures::future::try_join(send_requests_task, recv_requests_task).await {
+ Err(err) => error!("handle_connection: {remote_pubkey}, {remote_address}, {err:?}"),
+ Ok(out) => {
+ if let (Err(ref err), _) = out {
+ debug!("send_requests_task: {remote_pubkey}, {remote_address}, {err:?}");
+ record_error(err, &stats);
+ }
+ if let (_, Err(ref err)) = out {
+ debug!("recv_requests_task: {remote_pubkey}, {remote_address}, {err:?}");
+ record_error(err, &stats);
+ }
+ }
+ }
+ drop_connection(remote_pubkey, &connection, &cache).await;
+ if let Entry::Occupied(entry) = router.write().await.entry(remote_address) {
+ if entry.get().is_closed() {
+ entry.remove();
+ }
}
}
-async fn handle_connection(
- endpoint: &Endpoint,
+async fn recv_requests_task(
+ endpoint: Endpoint,
remote_address: SocketAddr,
remote_pubkey: Pubkey,
- connection: &Connection,
- remote_request_sender: &Sender,
+ connection: Connection,
+ remote_request_sender: Sender,
+ stats: Arc,
) -> Result<(), Error> {
loop {
let (send_stream, recv_stream) = connection.accept_bi().await?;
@@ -287,6 +444,7 @@ async fn handle_connection(
send_stream,
recv_stream,
remote_request_sender.clone(),
+ stats.clone(),
));
}
}
@@ -298,6 +456,7 @@ async fn handle_streams_task(
send_stream: SendStream,
recv_stream: RecvStream,
remote_request_sender: Sender,
+ stats: Arc,
) {
if let Err(err) = handle_streams(
&endpoint,
@@ -309,7 +468,8 @@ async fn handle_streams_task(
)
.await
{
- error!("handle_stream: {remote_address}, {remote_pubkey}, {err:?}");
+ debug!("handle_stream: {remote_address}, {remote_pubkey}, {err:?}");
+ record_error(&err, &stats);
}
}
@@ -352,32 +512,62 @@ async fn handle_streams(
send_stream.finish().await.map_err(Error::from)
}
+async fn send_requests_task(
+ endpoint: Endpoint,
+ remote_address: SocketAddr,
+ connection: Connection,
+ mut receiver: AsyncReceiver,
+ stats: Arc,
+) -> Result<(), Error> {
+ tokio::pin! {
+ let connection_closed = connection.closed();
+ }
+ loop {
+ tokio::select! {
+ biased;
+ request = receiver.recv() => {
+ match request {
+ None => return Ok(()),
+ Some(request) => tokio::task::spawn(send_request_task(
+ endpoint.clone(),
+ remote_address,
+ connection.clone(),
+ request,
+ stats.clone(),
+ )),
+ };
+ }
+ err = &mut connection_closed => return Err(Error::from(err)),
+ }
+ }
+}
+
async fn send_request_task(
endpoint: Endpoint,
+ remote_address: SocketAddr,
+ connection: Connection,
request: LocalRequest,
- remote_request_sender: Sender,
- cache: Arc>,
+ stats: Arc,
) {
- if let Err(err) = send_request(&endpoint, request, remote_request_sender, cache).await {
- error!("send_request_task: {err:?}");
+ if let Err(err) = send_request(endpoint, connection, request).await {
+ debug!("send_request: {remote_address}, {err:?}");
+ record_error(&err, &stats);
}
}
async fn send_request(
- endpoint: &Endpoint,
+ endpoint: Endpoint,
+ connection: Connection,
LocalRequest {
- remote_address,
+ remote_address: _,
bytes,
num_expected_responses,
response_sender,
}: LocalRequest,
- remote_request_sender: Sender,
- cache: Arc>,
) -> Result<(), Error> {
// Assert that send won't block.
debug_assert_eq!(response_sender.capacity(), None);
const READ_TIMEOUT_DURATION: Duration = Duration::from_secs(10);
- let connection = get_connection(endpoint, remote_address, remote_request_sender, cache).await?;
let (mut send_stream, mut recv_stream) = connection.open_bi().await?;
send_stream.write_all(&bytes).await?;
send_stream.finish().await?;
@@ -405,50 +595,70 @@ async fn send_request(
response_sender
.send((remote_address, chunk))
.map_err(|err| {
- close_quic_endpoint(endpoint);
+ close_quic_endpoint(&endpoint);
Error::from(err)
})
})
}
-async fn get_connection(
- endpoint: &Endpoint,
+async fn make_connection_task(
+ endpoint: Endpoint,
remote_address: SocketAddr,
remote_request_sender: Sender,
- cache: Arc>,
-) -> Result {
- let entry = get_cache_entry(remote_address, &cache).await;
+ receiver: AsyncReceiver,
+ bank_forks: Arc>,
+ prune_cache_pending: Arc,
+ router: Arc>>>,
+ cache: Arc>>,
+ stats: Arc,
+) {
+ if let Err(err) = make_connection(
+ endpoint,
+ remote_address,
+ remote_request_sender,
+ receiver,
+ bank_forks,
+ prune_cache_pending,
+ router,
+ cache,
+ stats.clone(),
+ )
+ .await
{
- let connection: Option = entry.read().await.clone();
- if let Some(connection) = connection {
- if connection.close_reason().is_none() {
- return Ok(connection);
- }
- }
+ debug!("make_connection: {remote_address}, {err:?}");
+ record_error(&err, &stats);
}
- let connection = {
- // Need to write lock here so that only one task initiates
- // a new connection to the same remote_address.
- let mut entry = entry.write().await;
- if let Some(connection) = entry.deref() {
- if connection.close_reason().is_none() {
- return Ok(connection.clone());
- }
- }
- let connection = endpoint
- .connect(remote_address, CONNECT_SERVER_NAME)?
- .await?;
- entry.insert(connection).clone()
- };
- tokio::task::spawn(handle_connection_error(
- endpoint.clone(),
+}
+
+async fn make_connection(
+ endpoint: Endpoint,
+ remote_address: SocketAddr,
+ remote_request_sender: Sender,
+ receiver: AsyncReceiver,
+ bank_forks: Arc>,
+ prune_cache_pending: Arc,
+ router: Arc>>>,
+ cache: Arc>>,
+ stats: Arc,
+) -> Result<(), Error> {
+ let connection = endpoint
+ .connect(remote_address, CONNECT_SERVER_NAME)?
+ .await?;
+ handle_connection(
+ endpoint,
connection.remote_address(),
get_remote_pubkey(&connection)?,
- connection.clone(),
+ connection,
remote_request_sender,
+ receiver,
+ bank_forks,
+ prune_cache_pending,
+ router,
cache,
- ));
- Ok(connection)
+ stats,
+ )
+ .await;
+ Ok(())
}
fn get_remote_pubkey(connection: &Connection) -> Result {
@@ -464,71 +674,95 @@ fn get_remote_pubkey(connection: &Connection) -> Result {
}
}
-async fn get_cache_entry(
- remote_address: SocketAddr,
- cache: &RwLock,
-) -> Arc>> {
- let key = (remote_address, /*remote_pubkey:*/ None);
- if let Some(entry) = cache.read().await.get(&key) {
- return entry.clone();
- }
- cache.write().await.entry(key).or_default().clone()
-}
-
async fn cache_connection(
- remote_address: SocketAddr,
remote_pubkey: Pubkey,
connection: Connection,
- cache: &RwLock,
+ bank_forks: Arc>,
+ prune_cache_pending: Arc,
+ router: Arc>>>,
+ cache: Arc>>,
) {
- // The 2nd cache entry with remote_pubkey == None allows to lookup an entry
- // only by SocketAddr when establishing outgoing connections.
- let entries: [Arc>>; 2] = {
- let mut cache = cache.write().await;
- if cache.len() >= CONNECTION_CACHE_CAPACITY {
- connection.close(
- CONNECTION_CLOSE_ERROR_CODE_DROPPED,
- CONNECTION_CLOSE_REASON_DROPPED,
- );
- return;
- }
- [Some(remote_pubkey), None].map(|remote_pubkey| {
- let key = (remote_address, remote_pubkey);
- cache.entry(key).or_default().clone()
- })
+ let (old, should_prune_cache) = {
+ let mut cache = cache.lock().await;
+ (
+ cache.insert(remote_pubkey, connection),
+ cache.len() >= CONNECTION_CACHE_CAPACITY.saturating_mul(2),
+ )
};
- let mut entry = entries[0].write().await;
- *entries[1].write().await = Some(connection.clone());
- if let Some(old) = entry.replace(connection) {
- drop(entry);
+ if let Some(old) = old {
old.close(
CONNECTION_CLOSE_ERROR_CODE_REPLACED,
CONNECTION_CLOSE_REASON_REPLACED,
);
}
+ if should_prune_cache && !prune_cache_pending.swap(true, Ordering::Relaxed) {
+ tokio::task::spawn(prune_connection_cache(
+ bank_forks,
+ prune_cache_pending,
+ router,
+ cache,
+ ));
+ }
}
async fn drop_connection(
- remote_address: SocketAddr,
remote_pubkey: Pubkey,
connection: &Connection,
- cache: &RwLock,
+ cache: &Mutex>,
) {
- if connection.close_reason().is_none() {
- connection.close(
- CONNECTION_CLOSE_ERROR_CODE_DROPPED,
- CONNECTION_CLOSE_REASON_DROPPED,
- );
- }
- let key = (remote_address, Some(remote_pubkey));
- if let Entry::Occupied(entry) = cache.write().await.entry(key) {
- if matches!(entry.get().read().await.deref(),
- Some(entry) if entry.stable_id() == connection.stable_id())
- {
+ connection.close(
+ CONNECTION_CLOSE_ERROR_CODE_DROPPED,
+ CONNECTION_CLOSE_REASON_DROPPED,
+ );
+ if let Entry::Occupied(entry) = cache.lock().await.entry(remote_pubkey) {
+ if entry.get().stable_id() == connection.stable_id() {
entry.remove();
}
}
- // Cache entry for (remote_address, None) will be lazily evicted.
+}
+
+async fn prune_connection_cache(
+ bank_forks: Arc>,
+ prune_cache_pending: Arc,
+ router: Arc>>>,
+ cache: Arc>>,
+) {
+ debug_assert!(prune_cache_pending.load(Ordering::Relaxed));
+ let staked_nodes = {
+ let root_bank = bank_forks.read().unwrap().root_bank();
+ root_bank.staked_nodes()
+ };
+ {
+ let mut cache = cache.lock().await;
+ if cache.len() < CONNECTION_CACHE_CAPACITY.saturating_mul(2) {
+ prune_cache_pending.store(false, Ordering::Relaxed);
+ return;
+ }
+ let mut connections: Vec<_> = cache
+ .drain()
+ .filter(|(_, connection)| connection.close_reason().is_none())
+ .map(|entry @ (pubkey, _)| {
+ let stake = staked_nodes.get(&pubkey).copied().unwrap_or_default();
+ (stake, entry)
+ })
+ .collect();
+ connections
+ .select_nth_unstable_by_key(CONNECTION_CACHE_CAPACITY, |&(stake, _)| Reverse(stake));
+ for (_, (_, connection)) in &connections[CONNECTION_CACHE_CAPACITY..] {
+ connection.close(
+ CONNECTION_CLOSE_ERROR_CODE_PRUNED,
+ CONNECTION_CLOSE_REASON_PRUNED,
+ );
+ }
+ cache.extend(
+ connections
+ .into_iter()
+ .take(CONNECTION_CACHE_CAPACITY)
+ .map(|(_, entry)| entry),
+ );
+ prune_cache_pending.store(false, Ordering::Relaxed);
+ }
+ router.write().await.retain(|_, sender| !sender.is_closed());
}
impl From> for Error {
@@ -537,11 +771,257 @@ impl From> for Error {
}
}
+#[derive(Default)]
+struct RepairQuicStats {
+ connect_error_invalid_remote_address: AtomicU64,
+ connect_error_other: AtomicU64,
+ connect_error_too_many_connections: AtomicU64,
+ connection_error_application_closed: AtomicU64,
+ connection_error_connection_closed: AtomicU64,
+ connection_error_locally_closed: AtomicU64,
+ connection_error_reset: AtomicU64,
+ connection_error_timed_out: AtomicU64,
+ connection_error_transport_error: AtomicU64,
+ connection_error_version_mismatch: AtomicU64,
+ invalid_identity: AtomicU64,
+ no_response_received: AtomicU64,
+ read_to_end_error_connection_lost: AtomicU64,
+ read_to_end_error_illegal_ordered_read: AtomicU64,
+ read_to_end_error_reset: AtomicU64,
+ read_to_end_error_too_long: AtomicU64,
+ read_to_end_error_unknown_stream: AtomicU64,
+ read_to_end_error_zero_rtt_rejected: AtomicU64,
+ read_to_end_timeout: AtomicU64,
+ router_try_send_error_full: AtomicU64,
+ write_error_connection_lost: AtomicU64,
+ write_error_stopped: AtomicU64,
+ write_error_unknown_stream: AtomicU64,
+ write_error_zero_rtt_rejected: AtomicU64,
+}
+
+async fn report_metrics_task(name: &'static str, stats: Arc) {
+ const METRICS_SUBMIT_CADENCE: Duration = Duration::from_secs(2);
+ loop {
+ tokio::time::sleep(METRICS_SUBMIT_CADENCE).await;
+ report_metrics(name, &stats);
+ }
+}
+
+fn record_error(err: &Error, stats: &RepairQuicStats) {
+ match err {
+ Error::CertificateError(_) => (),
+ Error::ChannelSendError => (),
+ Error::ConnectError(ConnectError::EndpointStopping) => {
+ add_metric!(stats.connect_error_other)
+ }
+ Error::ConnectError(ConnectError::TooManyConnections) => {
+ add_metric!(stats.connect_error_too_many_connections)
+ }
+ Error::ConnectError(ConnectError::InvalidDnsName(_)) => {
+ add_metric!(stats.connect_error_other)
+ }
+ Error::ConnectError(ConnectError::InvalidRemoteAddress(_)) => {
+ add_metric!(stats.connect_error_invalid_remote_address)
+ }
+ Error::ConnectError(ConnectError::NoDefaultClientConfig) => {
+ add_metric!(stats.connect_error_other)
+ }
+ Error::ConnectError(ConnectError::UnsupportedVersion) => {
+ add_metric!(stats.connect_error_other)
+ }
+ Error::ConnectionError(ConnectionError::VersionMismatch) => {
+ add_metric!(stats.connection_error_version_mismatch)
+ }
+ Error::ConnectionError(ConnectionError::TransportError(_)) => {
+ add_metric!(stats.connection_error_transport_error)
+ }
+ Error::ConnectionError(ConnectionError::ConnectionClosed(_)) => {
+ add_metric!(stats.connection_error_connection_closed)
+ }
+ Error::ConnectionError(ConnectionError::ApplicationClosed(_)) => {
+ add_metric!(stats.connection_error_application_closed)
+ }
+ Error::ConnectionError(ConnectionError::Reset) => add_metric!(stats.connection_error_reset),
+ Error::ConnectionError(ConnectionError::TimedOut) => {
+ add_metric!(stats.connection_error_timed_out)
+ }
+ Error::ConnectionError(ConnectionError::LocallyClosed) => {
+ add_metric!(stats.connection_error_locally_closed)
+ }
+ Error::InvalidIdentity(_) => add_metric!(stats.invalid_identity),
+ Error::IoError(_) => (),
+ Error::NoResponseReceived => add_metric!(stats.no_response_received),
+ Error::ReadToEndError(ReadToEndError::Read(ReadError::Reset(_))) => {
+ add_metric!(stats.read_to_end_error_reset)
+ }
+ Error::ReadToEndError(ReadToEndError::Read(ReadError::ConnectionLost(_))) => {
+ add_metric!(stats.read_to_end_error_connection_lost)
+ }
+ Error::ReadToEndError(ReadToEndError::Read(ReadError::UnknownStream)) => {
+ add_metric!(stats.read_to_end_error_unknown_stream)
+ }
+ Error::ReadToEndError(ReadToEndError::Read(ReadError::IllegalOrderedRead)) => {
+ add_metric!(stats.read_to_end_error_illegal_ordered_read)
+ }
+ Error::ReadToEndError(ReadToEndError::Read(ReadError::ZeroRttRejected)) => {
+ add_metric!(stats.read_to_end_error_zero_rtt_rejected)
+ }
+ Error::ReadToEndError(ReadToEndError::TooLong) => {
+ add_metric!(stats.read_to_end_error_too_long)
+ }
+ Error::ReadToEndTimeout => add_metric!(stats.read_to_end_timeout),
+ Error::TlsError(_) => (),
+ Error::WriteError(WriteError::Stopped(_)) => add_metric!(stats.write_error_stopped),
+ Error::WriteError(WriteError::ConnectionLost(_)) => {
+ add_metric!(stats.write_error_connection_lost)
+ }
+ Error::WriteError(WriteError::UnknownStream) => {
+ add_metric!(stats.write_error_unknown_stream)
+ }
+ Error::WriteError(WriteError::ZeroRttRejected) => {
+ add_metric!(stats.write_error_zero_rtt_rejected)
+ }
+ }
+}
+
+fn report_metrics(name: &'static str, stats: &RepairQuicStats) {
+ macro_rules! reset_metric {
+ ($metric: expr) => {
+ $metric.swap(0, Ordering::Relaxed)
+ };
+ }
+ datapoint_info!(
+ name,
+ (
+ "connect_error_invalid_remote_address",
+ reset_metric!(stats.connect_error_invalid_remote_address),
+ i64
+ ),
+ (
+ "connect_error_other",
+ reset_metric!(stats.connect_error_other),
+ i64
+ ),
+ (
+ "connect_error_too_many_connections",
+ reset_metric!(stats.connect_error_too_many_connections),
+ i64
+ ),
+ (
+ "connection_error_application_closed",
+ reset_metric!(stats.connection_error_application_closed),
+ i64
+ ),
+ (
+ "connection_error_connection_closed",
+ reset_metric!(stats.connection_error_connection_closed),
+ i64
+ ),
+ (
+ "connection_error_locally_closed",
+ reset_metric!(stats.connection_error_locally_closed),
+ i64
+ ),
+ (
+ "connection_error_reset",
+ reset_metric!(stats.connection_error_reset),
+ i64
+ ),
+ (
+ "connection_error_timed_out",
+ reset_metric!(stats.connection_error_timed_out),
+ i64
+ ),
+ (
+ "connection_error_transport_error",
+ reset_metric!(stats.connection_error_transport_error),
+ i64
+ ),
+ (
+ "connection_error_version_mismatch",
+ reset_metric!(stats.connection_error_version_mismatch),
+ i64
+ ),
+ (
+ "invalid_identity",
+ reset_metric!(stats.invalid_identity),
+ i64
+ ),
+ (
+ "no_response_received",
+ reset_metric!(stats.no_response_received),
+ i64
+ ),
+ (
+ "read_to_end_error_connection_lost",
+ reset_metric!(stats.read_to_end_error_connection_lost),
+ i64
+ ),
+ (
+ "read_to_end_error_illegal_ordered_read",
+ reset_metric!(stats.read_to_end_error_illegal_ordered_read),
+ i64
+ ),
+ (
+ "read_to_end_error_reset",
+ reset_metric!(stats.read_to_end_error_reset),
+ i64
+ ),
+ (
+ "read_to_end_error_too_long",
+ reset_metric!(stats.read_to_end_error_too_long),
+ i64
+ ),
+ (
+ "read_to_end_error_unknown_stream",
+ reset_metric!(stats.read_to_end_error_unknown_stream),
+ i64
+ ),
+ (
+ "read_to_end_error_zero_rtt_rejected",
+ reset_metric!(stats.read_to_end_error_zero_rtt_rejected),
+ i64
+ ),
+ (
+ "read_to_end_timeout",
+ reset_metric!(stats.read_to_end_timeout),
+ i64
+ ),
+ (
+ "router_try_send_error_full",
+ reset_metric!(stats.router_try_send_error_full),
+ i64
+ ),
+ (
+ "write_error_connection_lost",
+ reset_metric!(stats.write_error_connection_lost),
+ i64
+ ),
+ (
+ "write_error_stopped",
+ reset_metric!(stats.write_error_stopped),
+ i64
+ ),
+ (
+ "write_error_unknown_stream",
+ reset_metric!(stats.write_error_unknown_stream),
+ i64
+ ),
+ (
+ "write_error_zero_rtt_rejected",
+ reset_metric!(stats.write_error_zero_rtt_rejected),
+ i64
+ ),
+ );
+}
+
#[cfg(test)]
mod tests {
use {
super::*,
itertools::{izip, multiunzip},
+ solana_ledger::genesis_utils::{create_genesis_config, GenesisConfigInfo},
+ solana_runtime::bank::Bank,
solana_sdk::signature::Signer,
std::{iter::repeat_with, net::Ipv4Addr, time::Duration},
};
@@ -569,6 +1049,12 @@ mod tests {
repeat_with(crossbeam_channel::unbounded::)
.take(NUM_ENDPOINTS)
.unzip();
+ let bank_forks = {
+ let GenesisConfigInfo { genesis_config, .. } =
+ create_genesis_config(/*mint_lamports:*/ 100_000);
+ let bank = Bank::new_for_tests(&genesis_config);
+ BankForks::new_rw_arc(bank)
+ };
let (endpoints, senders, tasks): (Vec<_>, Vec<_>, Vec<_>) = multiunzip(
keypairs
.iter()
@@ -581,6 +1067,7 @@ mod tests {
socket,
IpAddr::V4(Ipv4Addr::LOCALHOST),
remote_request_sender,
+ bank_forks.clone(),
)
.unwrap()
}),
diff --git a/core/src/repair/repair_service.rs b/core/src/repair/repair_service.rs
index c7cfab03f8f..ad8bc413b68 100644
--- a/core/src/repair/repair_service.rs
+++ b/core/src/repair/repair_service.rs
@@ -1202,7 +1202,7 @@ mod test {
pub fn test_generate_and_send_duplicate_repairs() {
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
let bank = Bank::new_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let blockstore_path = get_tmp_ledger_path!();
let blockstore = Blockstore::open(&blockstore_path).unwrap();
let cluster_slots = ClusterSlots::default();
@@ -1301,7 +1301,7 @@ mod test {
pub fn test_update_duplicate_slot_repair_addr() {
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
let bank = Bank::new_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let dummy_addr = Some((
Pubkey::default(),
UdpSocket::bind("0.0.0.0:0").unwrap().local_addr().unwrap(),
diff --git a/core/src/repair/serve_repair.rs b/core/src/repair/serve_repair.rs
index 8ab42c28829..fb9256be7eb 100644
--- a/core/src/repair/serve_repair.rs
+++ b/core/src/repair/serve_repair.rs
@@ -1561,7 +1561,7 @@ mod tests {
fn test_serialize_deserialize_signed_request() {
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
let bank = Bank::new_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let cluster_info = Arc::new(new_test_cluster_info());
let serve_repair = ServeRepair::new(
cluster_info.clone(),
@@ -1611,7 +1611,7 @@ mod tests {
let mut bank = Bank::new_for_tests(&genesis_config);
bank.feature_set = Arc::new(FeatureSet::all_enabled());
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let serve_repair = ServeRepair::new(
cluster_info,
bank_forks,
@@ -1647,7 +1647,7 @@ mod tests {
fn test_map_requests_signed() {
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
let bank = Bank::new_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let cluster_info = Arc::new(new_test_cluster_info());
let serve_repair = ServeRepair::new(
cluster_info.clone(),
@@ -1976,7 +1976,7 @@ mod tests {
fn window_index_request() {
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
let bank = Bank::new_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let cluster_slots = ClusterSlots::default();
let cluster_info = Arc::new(new_test_cluster_info());
let serve_repair = ServeRepair::new(
@@ -2318,7 +2318,7 @@ mod tests {
fn test_repair_with_repair_validators() {
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
let bank = Bank::new_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+ let bank_forks = BankForks::new_rw_arc(bank);
let cluster_slots = ClusterSlots::default();
let cluster_info = Arc::new(new_test_cluster_info());
let me = cluster_info.my_contact_info();
diff --git a/core/src/replay_stage.rs b/core/src/replay_stage.rs
index 37067ce38f5..aaf4a09d266 100644
--- a/core/src/replay_stage.rs
+++ b/core/src/replay_stage.rs
@@ -66,6 +66,7 @@ use {
},
solana_sdk::{
clock::{BankId, Slot, MAX_PROCESSING_AGE, NUM_CONSECUTIVE_LEADER_SLOTS},
+ feature_set,
genesis_config::ClusterType,
hash::Hash,
pubkey::Pubkey,
@@ -544,6 +545,21 @@ impl ReplayStage {
let _exit = Finalizer::new(exit.clone());
let mut identity_keypair = cluster_info.keypair().clone();
let mut my_pubkey = identity_keypair.pubkey();
+ if my_pubkey != tower.node_pubkey {
+ // set-identity was called during the startup procedure, ensure the tower is consistent
+ // before starting the loop. further calls to set-identity will reload the tower in the loop
+ let my_old_pubkey = tower.node_pubkey;
+ tower = Self::load_tower(
+ tower_storage.as_ref(),
+ &my_pubkey,
+ &vote_account,
+ &bank_forks,
+ );
+ warn!(
+ "Identity changed during startup from {} to {}",
+ my_old_pubkey, my_pubkey
+ );
+ }
let (mut progress, mut heaviest_subtree_fork_choice) =
Self::initialize_progress_and_fork_choice_with_locked_bank_forks(
&bank_forks,
@@ -946,28 +962,12 @@ impl ReplayStage {
my_pubkey = identity_keypair.pubkey();
// Load the new identity's tower
- tower = Tower::restore(tower_storage.as_ref(), &my_pubkey)
- .and_then(|restored_tower| {
- let root_bank = bank_forks.read().unwrap().root_bank();
- let slot_history = root_bank.get_slot_history();
- restored_tower.adjust_lockouts_after_replay(
- root_bank.slot(),
- &slot_history,
- )
- })
- .unwrap_or_else(|err| {
- if err.is_file_missing() {
- Tower::new_from_bankforks(
- &bank_forks.read().unwrap(),
- &my_pubkey,
- &vote_account,
- )
- } else {
- error!("Failed to load tower for {}: {}", my_pubkey, err);
- std::process::exit(1);
- }
- });
-
+ tower = Self::load_tower(
+ tower_storage.as_ref(),
+ &my_pubkey,
+ &vote_account,
+ &bank_forks,
+ );
// Ensure the validator can land votes with the new identity before
// becoming leader
has_new_vote_been_rooted = !wait_for_vote_to_start_leader;
@@ -1117,6 +1117,39 @@ impl ReplayStage {
})
}
+ fn load_tower(
+ tower_storage: &dyn TowerStorage,
+ node_pubkey: &Pubkey,
+ vote_account: &Pubkey,
+ bank_forks: &Arc>,
+ ) -> Tower {
+ Tower::restore(tower_storage, node_pubkey)
+ .and_then(|restored_tower| {
+ let root_bank = bank_forks.read().unwrap().root_bank();
+ let slot_history = root_bank.get_slot_history();
+ restored_tower.adjust_lockouts_after_replay(root_bank.slot(), &slot_history)
+ })
+ .unwrap_or_else(|err| {
+ if err.is_file_missing() {
+ Tower::new_from_bankforks(
+ &bank_forks.read().unwrap(),
+ node_pubkey,
+ vote_account,
+ )
+ } else if err.is_too_old() {
+ warn!("Failed to load tower, too old for {}: {}. Creating a new tower from bankforks.", node_pubkey, err);
+ Tower::new_from_bankforks(
+ &bank_forks.read().unwrap(),
+ node_pubkey,
+ vote_account,
+ )
+ } else {
+ error!("Failed to load tower for {}: {}", node_pubkey, err);
+ std::process::exit(1);
+ }
+ })
+ }
+
fn check_for_vote_only_mode(
heaviest_bank_slot: Slot,
forks_root: Slot,
@@ -1238,8 +1271,12 @@ impl ReplayStage {
let duplicate_slots = blockstore
.duplicate_slots_iterator(bank_forks.root_bank().slot())
.unwrap();
- let duplicate_slot_hashes = duplicate_slots
- .filter_map(|slot| bank_forks.bank_hash(slot).map(|hash| (slot, hash)));
+ let duplicate_slot_hashes = duplicate_slots.filter_map(|slot| {
+ let bank = bank_forks.get(slot)?;
+ bank.feature_set
+ .is_active(&feature_set::consume_blockstore_duplicate_proofs::id())
+ .then_some((slot, bank.hash()))
+ });
(
bank_forks.root_bank(),
bank_forks.frozen_banks().values().cloned().collect(),
@@ -1360,14 +1397,22 @@ impl ReplayStage {
);
}
-
// Should not dump slots for which we were the leader
if Some(*my_pubkey) == leader_schedule_cache.slot_leader_at(*duplicate_slot, None) {
- panic!("We are attempting to dump a block that we produced. \
- This indicates that we are producing duplicate blocks, \
- or that there is a bug in our runtime/replay code which \
- causes us to compute different bank hashes than the rest of the cluster. \
- We froze slot {duplicate_slot} with hash {frozen_hash:?} while the cluster hash is {correct_hash}");
+ if let Some(bank) = bank_forks.read().unwrap().get(*duplicate_slot) {
+ bank_hash_details::write_bank_hash_details_file(&bank)
+ .map_err(|err| {
+ warn!("Unable to write bank hash details file: {err}");
+ })
+ .ok();
+ } else {
+ warn!("Unable to get bank for slot {duplicate_slot} from bank forks");
+ }
+ panic!("We are attempting to dump a block that we produced. \
+ This indicates that we are producing duplicate blocks, \
+ or that there is a bug in our runtime/replay code which \
+ causes us to compute different bank hashes than the rest of the cluster. \
+ We froze slot {duplicate_slot} with hash {frozen_hash:?} while the cluster hash is {correct_hash}");
}
let attempt_no = purge_repair_slot_counter
@@ -1518,7 +1563,11 @@ impl ReplayStage {
let bank = w_bank_forks
.remove(*slot)
.expect("BankForks should not have been purged yet");
- let _ = bank_hash_details::write_bank_hash_details_file(&bank);
+ bank_hash_details::write_bank_hash_details_file(&bank)
+ .map_err(|err| {
+ warn!("Unable to write bank hash details file: {err}");
+ })
+ .ok();
((*slot, bank.bank_id()), bank)
})
.unzip()
@@ -2107,7 +2156,11 @@ impl ReplayStage {
);
// If we previously marked this slot as duplicate in blockstore, let the state machine know
- if !duplicate_slots_tracker.contains(&slot) && blockstore.get_duplicate_slot(slot).is_some()
+ if bank
+ .feature_set
+ .is_active(&feature_set::consume_blockstore_duplicate_proofs::id())
+ && !duplicate_slots_tracker.contains(&slot)
+ && blockstore.get_duplicate_slot(slot).is_some()
{
let duplicate_state = DuplicateState::new_from_state(
slot,
@@ -2871,7 +2924,10 @@ impl ReplayStage {
SlotStateUpdate::BankFrozen(bank_frozen_state),
);
// If we previously marked this slot as duplicate in blockstore, let the state machine know
- if !duplicate_slots_tracker.contains(&bank.slot())
+ if bank
+ .feature_set
+ .is_active(&feature_set::consume_blockstore_duplicate_proofs::id())
+ && !duplicate_slots_tracker.contains(&bank.slot())
&& blockstore.get_duplicate_slot(bank.slot()).is_some()
{
let duplicate_state = DuplicateState::new_from_state(
@@ -2918,9 +2974,13 @@ impl ReplayStage {
Self::record_rewards(bank, rewards_recorder_sender);
if let Some(ref block_metadata_notifier) = block_metadata_notifier {
let block_metadata_notifier = block_metadata_notifier.read().unwrap();
+ let parent_blockhash = bank
+ .parent()
+ .map(|bank| bank.last_blockhash())
+ .unwrap_or_default();
block_metadata_notifier.notify_block_metadata(
bank.parent_slot(),
- &bank.parent_hash().to_string(),
+ &parent_blockhash.to_string(),
bank.slot(),
&bank.last_blockhash().to_string(),
&bank.rewards,
@@ -3869,6 +3929,7 @@ impl ReplayStage {
epoch_slots_frozen_slots: &mut EpochSlotsFrozenSlots,
drop_bank_sender: &Sender>>,
) {
+ bank_forks.read().unwrap().prune_program_cache(new_root);
let removed_banks = bank_forks.write().unwrap().set_root(
new_root,
accounts_background_request_sender,
@@ -4057,9 +4118,9 @@ pub(crate) mod tests {
crate::{
consensus::{
progress_map::{ValidatorStakeInfo, RETRANSMIT_BASE_DELAY_MS},
- tower_storage::NullTowerStorage,
+ tower_storage::{FileTowerStorage, NullTowerStorage},
tree_diff::TreeDiff,
- Tower,
+ Tower, VOTE_THRESHOLD_DEPTH,
},
replay_stage::ReplayStage,
vote_simulator::{self, VoteSimulator},
@@ -4081,7 +4142,7 @@ pub(crate) mod tests {
},
solana_runtime::{
accounts_background_service::AbsRequestSender,
- commitment::BlockCommitment,
+ commitment::{BlockCommitment, VOTE_THRESHOLD_SIZE},
genesis_utils::{GenesisConfigInfo, ValidatorVoteKeypairs},
},
solana_sdk::{
@@ -4105,6 +4166,7 @@ pub(crate) mod tests {
iter,
sync::{atomic::AtomicU64, Arc, RwLock},
},
+ tempfile::tempdir,
trees::{tr, Tree},
};
@@ -4359,7 +4421,7 @@ pub(crate) mod tests {
fn test_handle_new_root() {
let genesis_config = create_genesis_config(10_000).genesis_config;
let bank0 = Bank::new_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank0)));
+ let bank_forks = BankForks::new_rw_arc(bank0);
let root = 3;
let root_bank = Bank::new_from_parent(
@@ -4445,7 +4507,7 @@ pub(crate) mod tests {
fn test_handle_new_root_ahead_of_highest_super_majority_root() {
let genesis_config = create_genesis_config(10_000).genesis_config;
let bank0 = Bank::new_for_tests(&genesis_config);
- let bank_forks = Arc::new(RwLock::new(BankForks::new(bank0)));
+ let bank_forks = BankForks::new_rw_arc(bank0);
let confirmed_root = 1;
let fork = 2;
let bank1 = Bank::new_from_parent(
@@ -4848,7 +4910,7 @@ pub(crate) mod tests {
}
bank0.freeze();
let arc_bank0 = Arc::new(bank0);
- let bank_forks = Arc::new(RwLock::new(BankForks::new_from_banks(&[arc_bank0], 0)));
+ let bank_forks = BankForks::new_from_banks(&[arc_bank0], 0);
let exit = Arc::new(AtomicBool::new(false));
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
@@ -5027,7 +5089,7 @@ pub(crate) mod tests {
vote_simulator::initialize_state(&keypairs, 10_000);
let mut latest_validator_votes_for_frozen_banks =
LatestValidatorVotesForFrozenBanks::default();
- let bank0 = bank_forks.get(0).unwrap();
+ let bank0 = bank_forks.read().unwrap().get(0).unwrap();
let my_keypairs = keypairs.get(&my_node_pubkey).unwrap();
let vote_tx = vote_transaction::new_vote_transaction(
vec![0],
@@ -5039,7 +5101,6 @@ pub(crate) mod tests {
None,
);
- let bank_forks = RwLock::new(bank_forks);
let bank1 = Bank::new_from_parent(bank0.clone(), &my_node_pubkey, 1);
bank1.process_transaction(&vote_tx).unwrap();
bank1.freeze();
@@ -5372,7 +5433,7 @@ pub(crate) mod tests {
) {
let stake = 10_000;
let (bank_forks, _, _) = vote_simulator::initialize_state(all_keypairs, stake);
- let root_bank = bank_forks.root_bank();
+ let root_bank = bank_forks.read().unwrap().root_bank();
let mut propagated_stats = PropagatedStats {
total_epoch_stake: stake * all_keypairs.len() as u64,
..PropagatedStats::default()
@@ -5486,8 +5547,9 @@ pub(crate) mod tests {
let vote_pubkey = vote_keypairs.vote_keypair.pubkey();
let keypairs: HashMap<_, _> = vec![(node_pubkey, vote_keypairs)].into_iter().collect();
let stake = 10_000;
- let (mut bank_forks, mut progress_map, _) =
+ let (bank_forks_arc, mut progress_map, _) =
vote_simulator::initialize_state(&keypairs, stake);
+ let mut bank_forks = bank_forks_arc.write().unwrap();
let bank0 = bank_forks.get(0).unwrap();
bank_forks.insert(Bank::new_from_parent(bank0.clone(), &Pubkey::default(), 9));
@@ -5529,12 +5591,14 @@ pub(crate) mod tests {
// runs in `update_propagation_status`
assert!(!progress_map.get_leader_propagation_slot_must_exist(10).0);
+ drop(bank_forks);
+
let vote_tracker = VoteTracker::default();
vote_tracker.insert_vote(10, vote_pubkey);
ReplayStage::update_propagation_status(
&mut progress_map,
10,
- &RwLock::new(bank_forks),
+ &bank_forks_arc,
&vote_tracker,
&ClusterSlots::default(),
);
@@ -5578,8 +5642,9 @@ pub(crate) mod tests {
.collect();
let stake_per_validator = 10_000;
- let (mut bank_forks, mut progress_map, _) =
+ let (bank_forks_arc, mut progress_map, _) =
vote_simulator::initialize_state(&keypairs, stake_per_validator);
+ let mut bank_forks = bank_forks_arc.write().unwrap();
progress_map
.get_propagated_stats_mut(0)
.unwrap()
@@ -5620,12 +5685,14 @@ pub(crate) mod tests {
vote_tracker.insert_vote(10, *vote_pubkey);
}
+ drop(bank_forks);
+
// The last bank should reach propagation threshold, and propagate it all
// the way back through earlier leader banks
ReplayStage::update_propagation_status(
&mut progress_map,
10,
- &RwLock::new(bank_forks),
+ &bank_forks_arc,
&vote_tracker,
&ClusterSlots::default(),
);
@@ -5658,8 +5725,9 @@ pub(crate) mod tests {
.collect();
let stake_per_validator = 10_000;
- let (mut bank_forks, mut progress_map, _) =
+ let (bank_forks_arc, mut progress_map, _) =
vote_simulator::initialize_state(&keypairs, stake_per_validator);
+ let mut bank_forks = bank_forks_arc.write().unwrap();
progress_map
.get_propagated_stats_mut(0)
.unwrap()
@@ -5705,12 +5773,13 @@ pub(crate) mod tests {
// Insert a new vote
vote_tracker.insert_vote(10, vote_pubkeys[2]);
+ drop(bank_forks);
// The last bank should reach propagation threshold, and propagate it all
// the way back through earlier leader banks
ReplayStage::update_propagation_status(
&mut progress_map,
10,
- &RwLock::new(bank_forks),
+ &bank_forks_arc,
&vote_tracker,
&ClusterSlots::default(),
);
@@ -5816,7 +5885,8 @@ pub(crate) mod tests {
let bank0 = Bank::new_for_tests(&genesis_config::create_genesis_config(10000).0);
let parent_slot_bank =
Bank::new_from_parent(Arc::new(bank0), &Pubkey::default(), parent_slot);
- let mut bank_forks = BankForks::new(parent_slot_bank);
+ let bank_forks = BankForks::new_rw_arc(parent_slot_bank);
+ let mut bank_forks = bank_forks.write().unwrap();
let bank5 =
Bank::new_from_parent(bank_forks.get(parent_slot).unwrap(), &Pubkey::default(), 5);
bank_forks.insert(bank5);
@@ -6366,7 +6436,7 @@ pub(crate) mod tests {
&vote_tracker,
&ClusterSlots::default(),
&bank_forks,
- &mut HeaviestSubtreeForkChoice::new_from_bank_forks(&bank_forks.read().unwrap()),
+ &mut HeaviestSubtreeForkChoice::new_from_bank_forks(bank_forks.clone()),
&mut LatestValidatorVotesForFrozenBanks::default(),
);
@@ -8132,7 +8202,7 @@ pub(crate) mod tests {
let in_vote_only_mode = AtomicBool::new(false);
let genesis_config = create_genesis_config(10_000).genesis_config;
let bank0 = Bank::new_for_tests(&genesis_config);
- let bank_forks = RwLock::new(BankForks::new(bank0));
+ let bank_forks = BankForks::new_rw_arc(bank0);
ReplayStage::check_for_vote_only_mode(1000, 0, &in_vote_only_mode, &bank_forks);
assert!(in_vote_only_mode.load(Ordering::Relaxed));
ReplayStage::check_for_vote_only_mode(10, 0, &in_vote_only_mode, &bank_forks);
@@ -8290,4 +8360,54 @@ pub(crate) mod tests {
assert_eq!(reset_fork, Some(4));
assert_eq!(failures, vec![HeaviestForkFailures::LockedOut(4),]);
}
+
+ #[test]
+ fn test_tower_load_missing() {
+ let tower_file = tempdir().unwrap().into_path();
+ let tower_storage = FileTowerStorage::new(tower_file);
+ let node_pubkey = Pubkey::new_unique();
+ let vote_account = Pubkey::new_unique();
+ let tree = tr(0) / (tr(1) / (tr(3) / (tr(4))) / (tr(2) / (tr(5) / (tr(6)))));
+ let generate_votes = |pubkeys: Vec| {
+ pubkeys
+ .into_iter()
+ .zip(iter::once(vec![0, 1, 2, 5, 6]).chain(iter::repeat(vec![0, 1, 3, 4]).take(2)))
+ .collect()
+ };
+ let (vote_simulator, _blockstore) =
+ setup_forks_from_tree(tree, 3, Some(Box::new(generate_votes)));
+ let bank_forks = vote_simulator.bank_forks;
+
+ let tower =
+ ReplayStage::load_tower(&tower_storage, &node_pubkey, &vote_account, &bank_forks);
+ let expected_tower = Tower::new_for_tests(VOTE_THRESHOLD_DEPTH, VOTE_THRESHOLD_SIZE);
+ assert_eq!(tower.vote_state, expected_tower.vote_state);
+ assert_eq!(tower.node_pubkey, node_pubkey);
+ }
+
+ #[test]
+ fn test_tower_load() {
+ let tower_file = tempdir().unwrap().into_path();
+ let tower_storage = FileTowerStorage::new(tower_file);
+ let node_keypair = Keypair::new();
+ let node_pubkey = node_keypair.pubkey();
+ let vote_account = Pubkey::new_unique();
+ let tree = tr(0) / (tr(1) / (tr(3) / (tr(4))) / (tr(2) / (tr(5) / (tr(6)))));
+ let generate_votes = |pubkeys: Vec| {
+ pubkeys
+ .into_iter()
+ .zip(iter::once(vec![0, 1, 2, 5, 6]).chain(iter::repeat(vec![0, 1, 3, 4]).take(2)))
+ .collect()
+ };
+ let (vote_simulator, _blockstore) =
+ setup_forks_from_tree(tree, 3, Some(Box::new(generate_votes)));
+ let bank_forks = vote_simulator.bank_forks;
+ let expected_tower = Tower::new_random(node_pubkey);
+ expected_tower.save(&tower_storage, &node_keypair).unwrap();
+
+ let tower =
+ ReplayStage::load_tower(&tower_storage, &node_pubkey, &vote_account, &bank_forks);
+ assert_eq!(tower.vote_state, expected_tower.vote_state);
+ assert_eq!(tower.node_pubkey, expected_tower.node_pubkey);
+ }
}
diff --git a/core/src/shred_fetch_stage.rs b/core/src/shred_fetch_stage.rs
index 62733953cc7..703167b0b44 100644
--- a/core/src/shred_fetch_stage.rs
+++ b/core/src/shred_fetch_stage.rs
@@ -10,7 +10,9 @@ use {
solana_perf::packet::{PacketBatch, PacketBatchRecycler, PacketFlags, PACKETS_PER_BATCH},
solana_runtime::bank_forks::BankForks,
solana_sdk::{
- clock::DEFAULT_MS_PER_SLOT,
+ clock::{Slot, DEFAULT_MS_PER_SLOT},
+ epoch_schedule::EpochSchedule,
+ feature_set::{self, FeatureSet},
packet::{Meta, PACKET_DATA_SIZE},
pubkey::Pubkey,
},
@@ -50,12 +52,20 @@ impl ShredFetchStage {
.as_ref()
.map(|(_, cluster_info)| cluster_info.keypair().clone());
- let (mut last_root, mut last_slot, mut slots_per_epoch) = {
+ let (
+ mut last_root,
+ mut slots_per_epoch,
+ mut feature_set,
+ mut epoch_schedule,
+ mut last_slot,
+ ) = {
let bank_forks_r = bank_forks.read().unwrap();
let root_bank = bank_forks_r.root_bank();
(
root_bank.slot(),
root_bank.get_slots_in_epoch(root_bank.epoch()),
+ root_bank.feature_set.clone(),
+ *root_bank.epoch_schedule(),
bank_forks_r.highest_slot(),
)
};
@@ -69,6 +79,8 @@ impl ShredFetchStage {
last_slot = bank_forks_r.highest_slot();
bank_forks_r.root_bank()
};
+ feature_set = root_bank.feature_set.clone();
+ epoch_schedule = *root_bank.epoch_schedule();
last_root = root_bank.slot();
slots_per_epoch = root_bank.get_slots_in_epoch(root_bank.epoch());
keypair = repair_context
@@ -92,10 +104,19 @@ impl ShredFetchStage {
// Limit shreds to 2 epochs away.
let max_slot = last_slot + 2 * slots_per_epoch;
+ let should_drop_legacy_shreds =
+ |shred_slot| should_drop_legacy_shreds(shred_slot, &feature_set, &epoch_schedule);
let turbine_disabled = turbine_disabled.load(Ordering::Relaxed);
for packet in packet_batch.iter_mut().filter(|p| !p.meta().discard()) {
if turbine_disabled
- || should_discard_shred(packet, last_root, max_slot, shred_version, &mut stats)
+ || should_discard_shred(
+ packet,
+ last_root,
+ max_slot,
+ shred_version,
+ should_drop_legacy_shreds,
+ &mut stats,
+ )
{
packet.meta_mut().set_discard(true);
} else {
@@ -373,6 +394,22 @@ pub(crate) fn receive_repair_quic_packets(
}
}
+#[must_use]
+fn should_drop_legacy_shreds(
+ shred_slot: Slot,
+ feature_set: &FeatureSet,
+ epoch_schedule: &EpochSchedule,
+) -> bool {
+ match feature_set.activated_slot(&feature_set::drop_legacy_shreds::id()) {
+ None => false,
+ Some(feature_slot) => {
+ let feature_epoch = epoch_schedule.get_epoch(feature_slot);
+ let shred_epoch = epoch_schedule.get_epoch(shred_slot);
+ feature_epoch < shred_epoch
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use {
@@ -413,6 +450,7 @@ mod tests {
last_root,
max_slot,
shred_version,
+ |_| false, // should_drop_legacy_shreds
&mut stats,
));
let coding = solana_ledger::shred::Shredder::generate_coding_shreds(
@@ -426,6 +464,7 @@ mod tests {
last_root,
max_slot,
shred_version,
+ |_| false, // should_drop_legacy_shreds
&mut stats,
));
}
@@ -447,6 +486,7 @@ mod tests {
last_root,
max_slot,
shred_version,
+ |_| false, // should_drop_legacy_shreds
&mut stats,
));
assert_eq!(stats.index_overrun, 1);
@@ -468,12 +508,18 @@ mod tests {
3,
max_slot,
shred_version,
+ |_| false, // should_drop_legacy_shreds
&mut stats,
));
assert_eq!(stats.slot_out_of_range, 1);
assert!(should_discard_shred(
- &packet, last_root, max_slot, /*shred_version:*/ 345, &mut stats,
+ &packet,
+ last_root,
+ max_slot,
+ 345, // shred_version
+ |_| false, // should_drop_legacy_shreds
+ &mut stats,
));
assert_eq!(stats.shred_version_mismatch, 1);
@@ -483,6 +529,7 @@ mod tests {
last_root,
max_slot,
shred_version,
+ |_| false, // should_drop_legacy_shreds
&mut stats,
));
@@ -504,6 +551,7 @@ mod tests {
last_root,
max_slot,
shred_version,
+ |_| false, // should_drop_legacy_shreds
&mut stats,
));
@@ -515,6 +563,7 @@ mod tests {
last_root,
max_slot,
shred_version,
+ |_| false, // should_drop_legacy_shreds
&mut stats,
));
}
diff --git a/core/src/sigverify.rs b/core/src/sigverify.rs
index 8140efac7ec..b496452078d 100644
--- a/core/src/sigverify.rs
+++ b/core/src/sigverify.rs
@@ -16,7 +16,7 @@ use {
solana_sdk::{packet::Packet, saturating_add_assign},
};
-#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, AbiExample)]
pub struct SigverifyTracerPacketStats {
pub total_removed_before_sigverify_stage: usize,
pub total_tracer_packets_received_in_sigverify_stage: usize,
diff --git a/core/src/snapshot_packager_service.rs b/core/src/snapshot_packager_service.rs
index 4c90a8bd18d..6d81e2b5402 100644
--- a/core/src/snapshot_packager_service.rs
+++ b/core/src/snapshot_packager_service.rs
@@ -2,7 +2,7 @@ mod snapshot_gossip_manager;
use {
crossbeam_channel::{Receiver, Sender},
snapshot_gossip_manager::SnapshotGossipManager,
- solana_gossip::cluster_info::{ClusterInfo, MAX_LEGACY_SNAPSHOT_HASHES},
+ solana_gossip::cluster_info::ClusterInfo,
solana_measure::measure_us,
solana_perf::thread::renice_this_thread,
solana_runtime::{
@@ -39,25 +39,13 @@ impl SnapshotPackagerService {
snapshot_config: SnapshotConfig,
enable_gossip_push: bool,
) -> Self {
- let max_full_snapshot_hashes = std::cmp::min(
- MAX_LEGACY_SNAPSHOT_HASHES,
- snapshot_config
- .maximum_full_snapshot_archives_to_retain
- .get(),
- );
-
let t_snapshot_packager = Builder::new()
.name("solSnapshotPkgr".to_string())
.spawn(move || {
info!("SnapshotPackagerService has started");
renice_this_thread(snapshot_config.packager_thread_niceness_adj).unwrap();
- let mut snapshot_gossip_manager = enable_gossip_push.then(|| {
- SnapshotGossipManager::new(
- cluster_info,
- max_full_snapshot_hashes,
- starting_snapshot_hashes,
- )
- });
+ let mut snapshot_gossip_manager = enable_gossip_push
+ .then(|| SnapshotGossipManager::new(cluster_info, starting_snapshot_hashes));
loop {
if exit.load(Ordering::Relaxed) {
diff --git a/core/src/snapshot_packager_service/snapshot_gossip_manager.rs b/core/src/snapshot_packager_service/snapshot_gossip_manager.rs
index a2d7239b319..d4ab9863642 100644
--- a/core/src/snapshot_packager_service/snapshot_gossip_manager.rs
+++ b/core/src/snapshot_packager_service/snapshot_gossip_manager.rs
@@ -4,7 +4,7 @@ use {
snapshot_hash::{
FullSnapshotHash, IncrementalSnapshotHash, SnapshotHash, StartingSnapshotHashes,
},
- snapshot_package::{retain_max_n_elements, SnapshotKind},
+ snapshot_package::SnapshotKind,
},
solana_sdk::{clock::Slot, hash::Hash},
std::sync::Arc,
@@ -14,8 +14,6 @@ use {
pub struct SnapshotGossipManager {
cluster_info: Arc,
latest_snapshot_hashes: Option,
- max_legacy_full_snapshot_hashes: usize,
- legacy_full_snapshot_hashes: Vec,
}
impl SnapshotGossipManager {
@@ -24,14 +22,11 @@ impl SnapshotGossipManager {
#[must_use]
pub fn new(
cluster_info: Arc,
- max_legacy_full_snapshot_hashes: usize,
starting_snapshot_hashes: Option,
) -> Self {
let mut this = SnapshotGossipManager {
cluster_info,
latest_snapshot_hashes: None,
- max_legacy_full_snapshot_hashes,
- legacy_full_snapshot_hashes: Vec::default(),
};
if let Some(starting_snapshot_hashes) = starting_snapshot_hashes {
this.push_starting_snapshot_hashes(starting_snapshot_hashes);
@@ -49,10 +44,6 @@ impl SnapshotGossipManager {
);
}
self.push_latest_snapshot_hashes_to_cluster();
-
- // Handle legacy snapshot hashes here too
- // Once LegacySnapshotHashes are removed from CRDS, also remove them here
- self.push_legacy_full_snapshot_hash(starting_snapshot_hashes.full);
}
/// Push new snapshot hash to the cluster via CRDS
@@ -78,10 +69,6 @@ impl SnapshotGossipManager {
fn push_full_snapshot_hash(&mut self, full_snapshot_hash: FullSnapshotHash) {
self.update_latest_full_snapshot_hash(full_snapshot_hash);
self.push_latest_snapshot_hashes_to_cluster();
-
- // Handle legacy snapshot hashes here too
- // Once LegacySnapshotHashes are removed from CRDS, also remove them here
- self.push_legacy_full_snapshot_hash(full_snapshot_hash);
}
/// Push new incremental snapshot hash to the cluster via CRDS
@@ -146,22 +133,6 @@ impl SnapshotGossipManager {
and a new error case has been added that has not been handled here.",
);
}
-
- /// Add `full_snapshot_hash` to the vector of full snapshot hashes, then push that vector to
- /// the cluster via CRDS.
- fn push_legacy_full_snapshot_hash(&mut self, full_snapshot_hash: FullSnapshotHash) {
- self.legacy_full_snapshot_hashes.push(full_snapshot_hash);
-
- retain_max_n_elements(
- &mut self.legacy_full_snapshot_hashes,
- self.max_legacy_full_snapshot_hashes,
- );
-
- self.cluster_info
- .push_legacy_snapshot_hashes(clone_hashes_for_crds(
- self.legacy_full_snapshot_hashes.as_slice(),
- ));
- }
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
@@ -191,8 +162,3 @@ impl AsSnapshotHash for IncrementalSnapshotHash {
&self.0
}
}
-
-/// Clones and maps snapshot hashes into what CRDS expects
-fn clone_hashes_for_crds(hashes: &[impl AsSnapshotHash]) -> Vec<(Slot, Hash)> {
- hashes.iter().map(AsSnapshotHash::clone_for_crds).collect()
-}
diff --git a/core/src/tpu.rs b/core/src/tpu.rs
index 028a88f416e..93e76e70b17 100644
--- a/core/src/tpu.rs
+++ b/core/src/tpu.rs
@@ -34,7 +34,7 @@ use {
solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Keypair},
solana_streamer::{
nonblocking::quic::DEFAULT_WAIT_FOR_CHUNK_TIMEOUT,
- quic::{spawn_server, MAX_STAKED_CONNECTIONS, MAX_UNSTAKED_CONNECTIONS},
+ quic::{spawn_server_multi, MAX_STAKED_CONNECTIONS, MAX_UNSTAKED_CONNECTIONS},
streamer::StakedNodes,
},
solana_turbine::broadcast_stage::{BroadcastStage, BroadcastStageType},
@@ -57,8 +57,8 @@ pub struct TpuSockets {
pub transaction_forwards: Vec,
pub vote: Vec,
pub broadcast: Vec,
- pub transactions_quic: UdpSocket,
- pub transactions_forwards_quic: UdpSocket,
+ pub transactions_quic: Vec,
+ pub transactions_forwards_quic: Vec,
}
pub struct Tpu {
@@ -148,7 +148,7 @@ impl Tpu {
let (non_vote_sender, non_vote_receiver) = banking_tracer.create_channel_non_vote();
- let (_, tpu_quic_t) = spawn_server(
+ let (_, tpu_quic_t) = spawn_server_multi(
"quic_streamer_tpu",
transactions_quic_sockets,
keypair,
@@ -168,7 +168,7 @@ impl Tpu {
)
.unwrap();
- let (_, tpu_forwards_quic_t) = spawn_server(
+ let (_, tpu_forwards_quic_t) = spawn_server_multi(
"quic_streamer_tpu_forwards",
transactions_forwards_quic_sockets,
keypair,
diff --git a/core/src/tvu.rs b/core/src/tvu.rs
index 0b8358863fb..0fa619033ae 100644
--- a/core/src/tvu.rs
+++ b/core/src/tvu.rs
@@ -401,7 +401,7 @@ pub mod tests {
let starting_balance = 10_000;
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(starting_balance);
- let bank_forks = BankForks::new(Bank::new_for_tests(&genesis_config));
+ let bank_forks = BankForks::new_rw_arc(Bank::new_for_tests(&genesis_config));
let keypair = Arc::new(Keypair::new());
let (turbine_quic_endpoint_sender, _turbine_quic_endpoint_receiver) =
@@ -423,7 +423,7 @@ pub mod tests {
} = Blockstore::open_with_signal(&blockstore_path, BlockstoreOptions::default())
.expect("Expected to successfully open ledger");
let blockstore = Arc::new(blockstore);
- let bank = bank_forks.working_bank();
+ let bank = bank_forks.read().unwrap().working_bank();
let (exit, poh_recorder, poh_service, _entry_receiver) =
create_test_recorder(bank.clone(), blockstore.clone(), None, None);
let vote_keypair = Keypair::new();
@@ -435,7 +435,6 @@ pub mod tests {
let (replay_vote_sender, _replay_vote_receiver) = unbounded();
let (completed_data_sets_sender, _completed_data_sets_receiver) = unbounded();
let (_, gossip_confirmed_slots_receiver) = unbounded();
- let bank_forks = Arc::new(RwLock::new(bank_forks));
let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
let max_complete_rewards_slot = Arc::new(AtomicU64::default());
let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));
diff --git a/core/src/validator.rs b/core/src/validator.rs
index a0c39da7642..62ef6fe3762 100644
--- a/core/src/validator.rs
+++ b/core/src/validator.rs
@@ -108,7 +108,7 @@ use {
clock::Slot,
epoch_schedule::MAX_LEADER_SCHEDULE_EPOCH_OFFSET,
exit::Exit,
- genesis_config::GenesisConfig,
+ genesis_config::{ClusterType, GenesisConfig},
hash::Hash,
pubkey::Pubkey,
shred_version::compute_shred_version,
@@ -245,6 +245,7 @@ pub struct ValidatorConfig {
pub warp_slot: Option,
pub accounts_db_test_hash_calculation: bool,
pub accounts_db_skip_shrink: bool,
+ pub accounts_db_force_initial_clean: bool,
pub tpu_coalesce: Duration,
pub staked_nodes_overrides: Arc>>,
pub validator_exit: Arc>,
@@ -311,6 +312,7 @@ impl Default for ValidatorConfig {
warp_slot: None,
accounts_db_test_hash_calculation: false,
accounts_db_skip_shrink: false,
+ accounts_db_force_initial_clean: false,
tpu_coalesce: DEFAULT_TPU_COALESCE,
staked_nodes_overrides: Arc::new(RwLock::new(HashMap::new())),
validator_exit: Arc::new(RwLock::new(Exit::default())),
@@ -463,12 +465,12 @@ pub struct Validator {
ledger_metric_report_service: LedgerMetricReportService,
accounts_background_service: AccountsBackgroundService,
accounts_hash_verifier: AccountsHashVerifier,
- turbine_quic_endpoint: Endpoint,
+ turbine_quic_endpoint: Option,
turbine_quic_endpoint_runtime: Option,
- turbine_quic_endpoint_join_handle: solana_turbine::quic_endpoint::AsyncTryJoinHandle,
- repair_quic_endpoint: Endpoint,
+ turbine_quic_endpoint_join_handle: Option,
+ repair_quic_endpoint: Option,
repair_quic_endpoint_runtime: Option,
- repair_quic_endpoint_join_handle: repair::quic_endpoint::AsyncTryJoinHandle,
+ repair_quic_endpoint_join_handle: Option,
}
impl Validator {
@@ -934,7 +936,8 @@ impl Validator {
// (by both replay stage and banking stage)
let prioritization_fee_cache = Arc::new(PrioritizationFeeCache::default());
- let rpc_override_health_check = Arc::new(AtomicBool::new(false));
+ let rpc_override_health_check =
+ Arc::new(AtomicBool::new(config.rpc_config.disable_health_check));
let (
json_rpc_service,
pubsub_service,
@@ -971,7 +974,6 @@ impl Validator {
ledger_path,
config.validator_exit.clone(),
exit.clone(),
- config.known_validators.clone(),
rpc_override_health_check.clone(),
startup_verification_complete,
optimistically_confirmed_bank.clone(),
@@ -1134,11 +1136,11 @@ impl Validator {
.map_err(|err| format!("{} [{:?}]", &err, &err))?;
if banking_tracer.is_enabled() {
info!(
- "Enabled banking tracer (dir_byte_limit: {})",
+ "Enabled banking trace (dir_byte_limit: {})",
config.banking_trace_dir_byte_limit
);
} else {
- info!("Disabled banking tracer");
+ info!("Disabled banking trace");
}
let entry_notification_sender = entry_notifier_service
@@ -1151,56 +1153,74 @@ impl Validator {
// Outside test-validator crate, we always need a tokio runtime (and
// the respective handle) to initialize the turbine QUIC endpoint.
let current_runtime_handle = tokio::runtime::Handle::try_current();
- let turbine_quic_endpoint_runtime = current_runtime_handle.is_err().then(|| {
- tokio::runtime::Builder::new_multi_thread()
- .enable_all()
- .thread_name("solTurbineQuic")
- .build()
- .unwrap()
- });
+ let turbine_quic_endpoint_runtime = (current_runtime_handle.is_err()
+ && genesis_config.cluster_type != ClusterType::MainnetBeta)
+ .then(|| {
+ tokio::runtime::Builder::new_multi_thread()
+ .enable_all()
+ .thread_name("solTurbineQuic")
+ .build()
+ .unwrap()
+ });
let (turbine_quic_endpoint_sender, turbine_quic_endpoint_receiver) = unbounded();
let (
turbine_quic_endpoint,
turbine_quic_endpoint_sender,
turbine_quic_endpoint_join_handle,
- ) = solana_turbine::quic_endpoint::new_quic_endpoint(
- turbine_quic_endpoint_runtime
- .as_ref()
- .map(TokioRuntime::handle)
- .unwrap_or_else(|| current_runtime_handle.as_ref().unwrap()),
- &identity_keypair,
- node.sockets.tvu_quic,
- node.info
- .tvu(Protocol::QUIC)
- .expect("Operator must spin up node with valid QUIC TVU address")
- .ip(),
- turbine_quic_endpoint_sender,
- )
- .unwrap();
-
- // Repair quic endpoint.
- let repair_quic_endpoint_runtime = current_runtime_handle.is_err().then(|| {
- tokio::runtime::Builder::new_multi_thread()
- .enable_all()
- .thread_name("solRepairQuic")
- .build()
- .unwrap()
- });
- let (repair_quic_endpoint, repair_quic_endpoint_sender, repair_quic_endpoint_join_handle) =
- repair::quic_endpoint::new_quic_endpoint(
- repair_quic_endpoint_runtime
+ ) = if genesis_config.cluster_type == ClusterType::MainnetBeta {
+ let (sender, _receiver) = tokio::sync::mpsc::channel(1);
+ (None, sender, None)
+ } else {
+ solana_turbine::quic_endpoint::new_quic_endpoint(
+ turbine_quic_endpoint_runtime
.as_ref()
.map(TokioRuntime::handle)
.unwrap_or_else(|| current_runtime_handle.as_ref().unwrap()),
&identity_keypair,
- node.sockets.serve_repair_quic,
+ node.sockets.tvu_quic,
node.info
- .serve_repair(Protocol::QUIC)
- .expect("Operator must spin up node with valid QUIC serve-repair address")
+ .tvu(Protocol::QUIC)
+ .expect("Operator must spin up node with valid QUIC TVU address")
.ip(),
- repair_quic_endpoint_sender,
+ turbine_quic_endpoint_sender,
+ bank_forks.clone(),
)
- .unwrap();
+ .map(|(endpoint, sender, join_handle)| (Some(endpoint), sender, Some(join_handle)))
+ .unwrap()
+ };
+
+ // Repair quic endpoint.
+ let repair_quic_endpoint_runtime = (current_runtime_handle.is_err()
+ && genesis_config.cluster_type != ClusterType::MainnetBeta)
+ .then(|| {
+ tokio::runtime::Builder::new_multi_thread()
+ .enable_all()
+ .thread_name("solRepairQuic")
+ .build()
+ .unwrap()
+ });
+ let (repair_quic_endpoint, repair_quic_endpoint_sender, repair_quic_endpoint_join_handle) =
+ if genesis_config.cluster_type == ClusterType::MainnetBeta {
+ let (sender, _receiver) = tokio::sync::mpsc::channel(1);
+ (None, sender, None)
+ } else {
+ repair::quic_endpoint::new_quic_endpoint(
+ repair_quic_endpoint_runtime
+ .as_ref()
+ .map(TokioRuntime::handle)
+ .unwrap_or_else(|| current_runtime_handle.as_ref().unwrap()),
+ &identity_keypair,
+ node.sockets.serve_repair_quic,
+ node.info
+ .serve_repair(Protocol::QUIC)
+ .expect("Operator must spin up node with valid QUIC serve-repair address")
+ .ip(),
+ repair_quic_endpoint_sender,
+ bank_forks.clone(),
+ )
+ .map(|(endpoint, sender, join_handle)| (Some(endpoint), sender, Some(join_handle)))
+ .unwrap()
+ };
let (replay_vote_sender, replay_vote_receiver) = unbounded();
let tvu = Tvu::new(
@@ -1308,6 +1328,8 @@ impl Validator {
("id", id.to_string(), String),
("version", solana_version::version!(), String),
("cluster_type", cluster_type as u32, i64),
+ ("waited_for_supermajority", waited_for_supermajority, bool),
+ ("expected_shred_version", config.expected_shred_version, Option),
);
*start_progress.write().unwrap() = ValidatorStartProgress::Running;
@@ -1456,14 +1478,18 @@ impl Validator {
}
self.gossip_service.join().expect("gossip_service");
- repair::quic_endpoint::close_quic_endpoint(&self.repair_quic_endpoint);
+ if let Some(repair_quic_endpoint) = &self.repair_quic_endpoint {
+ repair::quic_endpoint::close_quic_endpoint(repair_quic_endpoint);
+ }
self.serve_repair_service
.join()
.expect("serve_repair_service");
- self.repair_quic_endpoint_runtime
- .map(|runtime| runtime.block_on(self.repair_quic_endpoint_join_handle))
- .transpose()
- .unwrap();
+ if let Some(repair_quic_endpoint_join_handle) = self.repair_quic_endpoint_join_handle {
+ self.repair_quic_endpoint_runtime
+ .map(|runtime| runtime.block_on(repair_quic_endpoint_join_handle))
+ .transpose()
+ .unwrap();
+ };
self.stats_reporter_service
.join()
.expect("stats_reporter_service");
@@ -1476,13 +1502,17 @@ impl Validator {
self.accounts_hash_verifier
.join()
.expect("accounts_hash_verifier");
- solana_turbine::quic_endpoint::close_quic_endpoint(&self.turbine_quic_endpoint);
+ if let Some(turbine_quic_endpoint) = &self.turbine_quic_endpoint {
+ solana_turbine::quic_endpoint::close_quic_endpoint(turbine_quic_endpoint);
+ }
self.tpu.join().expect("tpu");
self.tvu.join().expect("tvu");
- self.turbine_quic_endpoint_runtime
- .map(|runtime| runtime.block_on(self.turbine_quic_endpoint_join_handle))
- .transpose()
- .unwrap();
+ if let Some(turbine_quic_endpoint_join_handle) = self.turbine_quic_endpoint_join_handle {
+ self.turbine_quic_endpoint_runtime
+ .map(|runtime| runtime.block_on(turbine_quic_endpoint_join_handle))
+ .transpose()
+ .unwrap();
+ }
self.completed_data_sets_service
.join()
.expect("completed_data_sets_service");
@@ -1724,6 +1754,7 @@ fn load_blockstore(
shrink_ratio: config.accounts_shrink_ratio,
accounts_db_test_hash_calculation: config.accounts_db_test_hash_calculation,
accounts_db_skip_shrink: config.accounts_db_skip_shrink,
+ accounts_db_force_initial_clean: config.accounts_db_force_initial_clean,
runtime_config: config.runtime_config.clone(),
use_snapshot_archives_at_startup: config.use_snapshot_archives_at_startup,
..blockstore_processor::ProcessOptions::default()
@@ -2579,7 +2610,7 @@ mod tests {
);
let (genesis_config, _mint_keypair) = create_genesis_config(1);
- let bank_forks = RwLock::new(BankForks::new(Bank::new_for_tests(&genesis_config)));
+ let bank_forks = BankForks::new_rw_arc(Bank::new_for_tests(&genesis_config));
let mut config = ValidatorConfig::default_for_test();
let rpc_override_health_check = Arc::new(AtomicBool::new(false));
let start_progress = Arc::new(RwLock::new(ValidatorStartProgress::default()));
@@ -2609,11 +2640,11 @@ mod tests {
);
// bank=1, wait=0, should pass, bank is past the wait slot
- let bank_forks = RwLock::new(BankForks::new(Bank::new_from_parent(
+ let bank_forks = BankForks::new_rw_arc(Bank::new_from_parent(
bank_forks.read().unwrap().root_bank(),
&Pubkey::default(),
1,
- )));
+ ));
config.wait_for_supermajority = Some(0);
assert!(!wait_for_supermajority(
&config,
diff --git a/core/src/vote_simulator.rs b/core/src/vote_simulator.rs
index 79c418bcc78..77cf818f620 100644
--- a/core/src/vote_simulator.rs
+++ b/core/src/vote_simulator.rs
@@ -57,7 +57,7 @@ impl VoteSimulator {
validator_keypairs,
node_pubkeys,
vote_pubkeys,
- bank_forks: Arc::new(RwLock::new(bank_forks)),
+ bank_forks,
progress,
heaviest_subtree_fork_choice,
latest_validator_votes_for_frozen_banks: LatestValidatorVotesForFrozenBanks::default(),
@@ -296,13 +296,14 @@ impl VoteSimulator {
false
}
+ #[allow(clippy::type_complexity)]
fn init_state(
num_keypairs: usize,
) -> (
HashMap,
Vec,
Vec,
- BankForks,
+ Arc>,
ProgressMap,
HeaviestSubtreeForkChoice,
) {
@@ -338,7 +339,11 @@ impl VoteSimulator {
pub fn initialize_state(
validator_keypairs_map: &HashMap,
stake: u64,
-) -> (BankForks, ProgressMap, HeaviestSubtreeForkChoice) {
+) -> (
+ Arc>,
+ ProgressMap,
+ HeaviestSubtreeForkChoice,
+) {
let validator_keypairs: Vec<_> = validator_keypairs_map.values().collect();
let GenesisConfigInfo {
mut genesis_config,
@@ -366,7 +371,8 @@ pub fn initialize_state(
0,
ForkProgress::new_from_bank(&bank0, bank0.collector_id(), &Pubkey::default(), None, 0, 0),
);
- let bank_forks = BankForks::new(bank0);
- let heaviest_subtree_fork_choice = HeaviestSubtreeForkChoice::new_from_bank_forks(&bank_forks);
+ let bank_forks = BankForks::new_rw_arc(bank0);
+ let heaviest_subtree_fork_choice =
+ HeaviestSubtreeForkChoice::new_from_bank_forks(bank_forks.clone());
(bank_forks, progress, heaviest_subtree_fork_choice)
}
diff --git a/core/src/window_service.rs b/core/src/window_service.rs
index a68a20e2078..a36692cc7ef 100644
--- a/core/src/window_service.rs
+++ b/core/src/window_service.rs
@@ -1,6 +1,7 @@
//! `window_service` handles the data plane incoming shreds, storing them in
//! blockstore and retransmitting where required
//!
+
use {
crate::{
cluster_info_vote_listener::VerifiedVoteReceiver,
@@ -28,7 +29,12 @@ use {
solana_metrics::inc_new_counter_error,
solana_perf::packet::{Packet, PacketBatch},
solana_rayon_threadlimit::get_thread_count,
- solana_sdk::clock::Slot,
+ solana_runtime::bank_forks::BankForks,
+ solana_sdk::{
+ clock::{Slot, DEFAULT_MS_PER_SLOT},
+ feature_set,
+ },
+ solana_turbine::cluster_nodes,
std::{
cmp::Reverse,
collections::{HashMap, HashSet},
@@ -142,12 +148,31 @@ fn run_check_duplicate(
blockstore: &Blockstore,
shred_receiver: &Receiver,
duplicate_slots_sender: &DuplicateSlotSender,
+ bank_forks: &RwLock,
) -> Result<()> {
+ let mut root_bank = bank_forks.read().unwrap().root_bank();
+ let mut last_updated = Instant::now();
let check_duplicate = |shred: PossibleDuplicateShred| -> Result<()> {
+ if last_updated.elapsed().as_millis() as u64 > DEFAULT_MS_PER_SLOT {
+ // Grabs bank forks lock once a slot
+ last_updated = Instant::now();
+ root_bank = bank_forks.read().unwrap().root_bank();
+ }
let shred_slot = shred.slot();
+ let send_index_and_erasure_conflicts = cluster_nodes::check_feature_activation(
+ &feature_set::index_erasure_conflict_duplicate_proofs::id(),
+ shred_slot,
+ &root_bank,
+ );
let (shred1, shred2) = match shred {
- PossibleDuplicateShred::LastIndexConflict(shred, conflict) => (shred, conflict),
- PossibleDuplicateShred::ErasureConflict(shred, conflict) => (shred, conflict),
+ PossibleDuplicateShred::LastIndexConflict(shred, conflict)
+ | PossibleDuplicateShred::ErasureConflict(shred, conflict) => {
+ if send_index_and_erasure_conflicts {
+ (shred, conflict)
+ } else {
+ return Ok(());
+ }
+ }
PossibleDuplicateShred::Exists(shred) => {
// Unlike the other cases we have to wait until here to decide to handle the duplicate and store
// in blockstore. This is because the duplicate could have been part of the same insert batch,
@@ -342,6 +367,7 @@ impl WindowService {
let outstanding_requests = Arc::>::default();
let cluster_info = repair_info.cluster_info.clone();
+ let bank_forks = repair_info.bank_forks.clone();
let repair_service = RepairService::new(
blockstore.clone(),
@@ -366,6 +392,7 @@ impl WindowService {
blockstore.clone(),
duplicate_receiver,
duplicate_slots_sender,
+ bank_forks,
);
let t_insert = Self::start_window_insert_thread(
@@ -392,6 +419,7 @@ impl WindowService {
blockstore: Arc,
duplicate_receiver: Receiver,
duplicate_slots_sender: DuplicateSlotSender,
+ bank_forks: Arc>,
) -> JoinHandle<()> {
let handle_error = || {
inc_new_counter_error!("solana-check-duplicate-error", 1, 1);
@@ -405,6 +433,7 @@ impl WindowService {
&blockstore,
&duplicate_receiver,
&duplicate_slots_sender,
+ &bank_forks,
) {
if Self::should_exit_on_error(e, &handle_error) {
break;
@@ -507,9 +536,11 @@ mod test {
solana_gossip::contact_info::ContactInfo,
solana_ledger::{
blockstore::{make_many_slot_entries, Blockstore},
+ genesis_utils::create_genesis_config,
get_tmp_ledger_path_auto_delete,
shred::{ProcessShredsStats, Shredder},
},
+ solana_runtime::bank::Bank,
solana_sdk::{
hash::Hash,
signature::{Keypair, Signer},
@@ -556,6 +587,8 @@ mod test {
#[test]
fn test_run_check_duplicate() {
let ledger_path = get_tmp_ledger_path_auto_delete!();
+ let genesis_config = create_genesis_config(10_000).genesis_config;
+ let bank_forks = BankForks::new_rw_arc(Bank::new_for_tests(&genesis_config));
let blockstore = Arc::new(Blockstore::open(ledger_path.path()).unwrap());
let (sender, receiver) = unbounded();
let (duplicate_slot_sender, duplicate_slot_receiver) = unbounded();
@@ -587,6 +620,7 @@ mod test {
&blockstore,
&receiver,
&duplicate_slot_sender,
+ &bank_forks,
)
.unwrap();
@@ -616,6 +650,8 @@ mod test {
Arc::new(keypair),
SocketAddrSpace::Unspecified,
));
+ let genesis_config = create_genesis_config(10_000).genesis_config;
+ let bank_forks = BankForks::new_rw_arc(Bank::new_for_tests(&genesis_config));
// Start duplicate thread receiving and inserting duplicates
let t_check_duplicate = WindowService::start_check_duplicate_thread(
@@ -624,6 +660,7 @@ mod test {
blockstore.clone(),
duplicate_shred_receiver,
duplicate_slot_sender,
+ bank_forks,
);
let handle_duplicate = |shred| {
diff --git a/core/tests/epoch_accounts_hash.rs b/core/tests/epoch_accounts_hash.rs
index 1f6eb702769..5cc507b1551 100755
--- a/core/tests/epoch_accounts_hash.rs
+++ b/core/tests/epoch_accounts_hash.rs
@@ -116,13 +116,18 @@ impl TestEnvironment {
..snapshot_config
};
- let mut bank_forks = BankForks::new(Bank::new_for_tests_with_config(
+ let bank_forks = BankForks::new_rw_arc(Bank::new_for_tests_with_config(
&genesis_config_info.genesis_config,
BankTestConfig::default(),
));
- bank_forks.set_snapshot_config(Some(snapshot_config.clone()));
- bank_forks.set_accounts_hash_interval_slots(Self::ACCOUNTS_HASH_INTERVAL);
- let bank_forks = Arc::new(RwLock::new(bank_forks));
+ bank_forks
+ .write()
+ .unwrap()
+ .set_snapshot_config(Some(snapshot_config.clone()));
+ bank_forks
+ .write()
+ .unwrap()
+ .set_accounts_hash_interval_slots(Self::ACCOUNTS_HASH_INTERVAL);
let exit = Arc::new(AtomicBool::new(false));
let node_id = Arc::new(Keypair::new());
@@ -264,7 +269,7 @@ fn test_epoch_accounts_hash_basic(test_environment: TestEnvironment) {
const NUM_EPOCHS_TO_TEST: u64 = 2;
const SET_ROOT_INTERVAL: Slot = 3;
- let bank_forks = &test_environment.bank_forks;
+ let bank_forks = test_environment.bank_forks.clone();
let mut expected_epoch_accounts_hash = None;
@@ -299,6 +304,7 @@ fn test_epoch_accounts_hash_basic(test_environment: TestEnvironment) {
// Set roots so that ABS requests are sent (this is what requests EAH calculations)
if bank.slot().checked_rem(SET_ROOT_INTERVAL).unwrap() == 0 {
trace!("rooting bank {}", bank.slot());
+ bank_forks.read().unwrap().prune_program_cache(bank.slot());
bank_forks.write().unwrap().set_root(
bank.slot(),
&test_environment
@@ -379,7 +385,7 @@ fn test_snapshots_have_expected_epoch_accounts_hash() {
let test_environment =
TestEnvironment::new_with_snapshots(FULL_SNAPSHOT_INTERVAL, FULL_SNAPSHOT_INTERVAL);
- let bank_forks = &test_environment.bank_forks;
+ let bank_forks = test_environment.bank_forks.clone();
let slots_per_epoch = test_environment
.genesis_config_info
@@ -411,6 +417,7 @@ fn test_snapshots_have_expected_epoch_accounts_hash() {
// Root every bank. This is what a normal validator does as well.
// `set_root()` is also what requests snapshots and EAH calculations.
+ bank_forks.read().unwrap().prune_program_cache(bank.slot());
bank_forks.write().unwrap().set_root(
bank.slot(),
&test_environment
@@ -461,6 +468,7 @@ fn test_snapshots_have_expected_epoch_accounts_hash() {
AccountShrinkThreshold::default(),
true,
true,
+ false,
true,
None,
None,
@@ -495,7 +503,7 @@ fn test_background_services_request_handling_for_epoch_accounts_hash() {
let test_environment =
TestEnvironment::new_with_snapshots(FULL_SNAPSHOT_INTERVAL, FULL_SNAPSHOT_INTERVAL);
- let bank_forks = &test_environment.bank_forks;
+ let bank_forks = test_environment.bank_forks.clone();
let snapshot_config = &test_environment.snapshot_config;
let slots_per_epoch = test_environment
@@ -529,10 +537,11 @@ fn test_background_services_request_handling_for_epoch_accounts_hash() {
// Based on the EAH start and snapshot interval, pick a slot to mass-root all the banks in
// this range such that an EAH request will be sent and also a snapshot request.
let eah_start_slot = epoch_accounts_hash_utils::calculation_start(&bank);
- let set_root_slot = next_multiple_of(eah_start_slot, FULL_SNAPSHOT_INTERVAL);
+ let set_root_slot = eah_start_slot.next_multiple_of(FULL_SNAPSHOT_INTERVAL);
if bank.block_height() == set_root_slot {
info!("Calling set_root() on bank {}...", bank.slot());
+ bank_forks.read().unwrap().prune_program_cache(bank.slot());
bank_forks.write().unwrap().set_root(
bank.slot(),
&test_environment
@@ -576,7 +585,7 @@ fn test_epoch_accounts_hash_and_warping() {
solana_logger::setup();
let test_environment = TestEnvironment::new();
- let bank_forks = &test_environment.bank_forks;
+ let bank_forks = test_environment.bank_forks.clone();
let bank = bank_forks.read().unwrap().working_bank();
let epoch_schedule = test_environment
.genesis_config_info
@@ -589,6 +598,7 @@ fn test_epoch_accounts_hash_and_warping() {
let eah_stop_slot_in_next_epoch =
epoch_schedule.get_first_slot_in_epoch(bank.epoch() + 1) + eah_stop_offset;
// have to set root here so that we can flush the write cache
+ bank_forks.read().unwrap().prune_program_cache(bank.slot());
bank_forks.write().unwrap().set_root(
bank.slot(),
&test_environment
@@ -661,16 +671,3 @@ fn test_epoch_accounts_hash_and_warping() {
.wait_get_epoch_accounts_hash();
info!("Waiting for epoch accounts hash... DONE");
}
-
-// Copy the impl of `next_multiple_of` since it is nightly-only experimental.
-// https://doc.rust-lang.org/std/primitive.u64.html#method.next_multiple_of
-// https://github.com/rust-lang/rust/issues/88581
-// https://github.com/rust-lang/rust/pull/88582
-// https://github.com/jhpratt/rust/blob/727a4fc7e3f836938dfeb4a2ab237cfca612222d/library/core/src/num/uint_macros.rs#L1811-L1837
-const fn next_multiple_of(lhs: u64, rhs: u64) -> u64 {
- #![allow(clippy::arithmetic_side_effects)]
- match lhs % rhs {
- 0 => lhs,
- r => lhs + (rhs - r),
- }
-}
diff --git a/core/tests/snapshots.rs b/core/tests/snapshots.rs
index b61e84a9081..9a862138a22 100644
--- a/core/tests/snapshots.rs
+++ b/core/tests/snapshots.rs
@@ -66,7 +66,7 @@ use {
};
struct SnapshotTestConfig {
- bank_forks: BankForks,
+ bank_forks: Arc>,
genesis_config_info: GenesisConfigInfo,
snapshot_config: SnapshotConfig,
incremental_snapshot_archives_dir: TempDir,
@@ -109,7 +109,8 @@ impl SnapshotTestConfig {
);
bank0.freeze();
bank0.set_startup_verification_complete();
- let mut bank_forks = BankForks::new(bank0);
+ let bank_forks_arc = BankForks::new_rw_arc(bank0);
+ let mut bank_forks = bank_forks_arc.write().unwrap();
bank_forks.accounts_hash_interval_slots = accounts_hash_interval_slots;
let snapshot_config = SnapshotConfig {
@@ -125,7 +126,7 @@ impl SnapshotTestConfig {
};
bank_forks.set_snapshot_config(Some(snapshot_config.clone()));
SnapshotTestConfig {
- bank_forks,
+ bank_forks: bank_forks_arc.clone(),
genesis_config_info,
snapshot_config,
incremental_snapshot_archives_dir,
@@ -138,11 +139,12 @@ impl SnapshotTestConfig {
}
fn restore_from_snapshot(
- old_bank_forks: &BankForks,
+ old_bank_forks: Arc>,
old_last_slot: Slot,
old_genesis_config: &GenesisConfig,
account_paths: &[PathBuf],
) {
+ let old_bank_forks = old_bank_forks.read().unwrap();
let snapshot_config = old_bank_forks.snapshot_config.as_ref().unwrap();
let old_last_bank = old_bank_forks.get(old_last_slot).unwrap();
@@ -171,6 +173,7 @@ fn restore_from_snapshot(
check_hash_calculation,
false,
false,
+ false,
Some(ACCOUNTS_DB_CONFIG_FOR_TESTING),
None,
Arc::default(),
@@ -197,7 +200,7 @@ fn run_bank_forks_snapshot_n(
{
solana_logger::setup();
// Set up snapshotting config
- let mut snapshot_test_config = SnapshotTestConfig::new(
+ let snapshot_test_config = SnapshotTestConfig::new(
snapshot_version,
cluster_type,
set_root_interval,
@@ -205,7 +208,7 @@ fn run_bank_forks_snapshot_n(
DISABLED_SNAPSHOT_ARCHIVE_INTERVAL,
);
- let bank_forks = &mut snapshot_test_config.bank_forks;
+ let bank_forks = snapshot_test_config.bank_forks.clone();
let mint_keypair = &snapshot_test_config.genesis_config_info.mint_keypair;
let (accounts_package_sender, _accounts_package_receiver) = crossbeam_channel::unbounded();
@@ -218,16 +221,23 @@ fn run_bank_forks_snapshot_n(
accounts_package_sender,
};
for slot in 1..=last_slot {
- let mut bank =
- Bank::new_from_parent(bank_forks[slot - 1].clone(), &Pubkey::default(), slot);
+ let mut bank = Bank::new_from_parent(
+ bank_forks.read().unwrap().get(slot - 1).unwrap().clone(),
+ &Pubkey::default(),
+ slot,
+ );
f(&mut bank, mint_keypair);
- let bank = bank_forks.insert(bank);
+ let bank = bank_forks.write().unwrap().insert(bank);
// Set root to make sure we don't end up with too many account storage entries
// and to allow snapshotting of bank and the purging logic on status_cache to
// kick in
if slot % set_root_interval == 0 || slot == last_slot {
// set_root should send a snapshot request
- bank_forks.set_root(bank.slot(), &request_sender, None);
+ bank_forks.read().unwrap().prune_program_cache(bank.slot());
+ bank_forks
+ .write()
+ .unwrap()
+ .set_root(bank.slot(), &request_sender, None);
snapshot_request_handler.handle_snapshot_requests(
false,
0,
@@ -238,7 +248,7 @@ fn run_bank_forks_snapshot_n(
}
// Generate a snapshot package for last bank
- let last_bank = bank_forks.get(last_slot).unwrap();
+ let last_bank = bank_forks.read().unwrap().get(last_slot).unwrap();
let snapshot_config = &snapshot_test_config.snapshot_config;
let bank_snapshots_dir = &snapshot_config.bank_snapshots_dir;
let last_bank_snapshot_info = snapshot_utils::get_highest_bank_snapshot_pre(bank_snapshots_dir)
@@ -277,7 +287,12 @@ fn run_bank_forks_snapshot_n(
let (_tmp_dir, temporary_accounts_dir) = create_tmp_accounts_dir_for_tests();
let account_paths = &[temporary_accounts_dir];
let genesis_config = &snapshot_test_config.genesis_config_info.genesis_config;
- restore_from_snapshot(bank_forks, last_slot, genesis_config, account_paths);
+ restore_from_snapshot(
+ snapshot_test_config.bank_forks.clone(),
+ last_slot,
+ genesis_config,
+ account_paths,
+ );
}
#[test_case(V1_2_0, Development)]
@@ -330,7 +345,7 @@ fn test_concurrent_snapshot_packaging(
const MAX_BANK_SNAPSHOTS_TO_RETAIN: usize = 8;
// Set up snapshotting config
- let mut snapshot_test_config = SnapshotTestConfig::new(
+ let snapshot_test_config = SnapshotTestConfig::new(
snapshot_version,
cluster_type,
1,
@@ -338,7 +353,7 @@ fn test_concurrent_snapshot_packaging(
DISABLED_SNAPSHOT_ARCHIVE_INTERVAL,
);
- let bank_forks = &mut snapshot_test_config.bank_forks;
+ let bank_forks = snapshot_test_config.bank_forks.clone();
let snapshot_config = &snapshot_test_config.snapshot_config;
let bank_snapshots_dir = &snapshot_config.bank_snapshots_dir;
let full_snapshot_archives_dir = &snapshot_config.full_snapshot_archives_dir;
@@ -347,7 +362,7 @@ fn test_concurrent_snapshot_packaging(
let genesis_config = &snapshot_test_config.genesis_config_info.genesis_config;
// Take snapshot of zeroth bank
- let bank0 = bank_forks.get(0).unwrap();
+ let bank0 = bank_forks.read().unwrap().get(0).unwrap();
let storages = bank0.get_snapshot_storages(None);
let slot_deltas = bank0.status_cache.read().unwrap().root_slot_deltas();
snapshot_bank_utils::add_bank_snapshot(
@@ -380,7 +395,7 @@ fn test_concurrent_snapshot_packaging(
for i in 0..MAX_BANK_SNAPSHOTS_TO_RETAIN + 2 {
let parent_slot = i as Slot;
let bank = Bank::new_from_parent(
- bank_forks[parent_slot].clone(),
+ bank_forks.read().unwrap().get(parent_slot).unwrap().clone(),
&Pubkey::default(),
parent_slot + 1,
);
@@ -424,10 +439,14 @@ fn test_concurrent_snapshot_packaging(
);
accounts_package_sender.send(accounts_package).unwrap();
- bank_forks.insert(bank);
+ bank_forks.write().unwrap().insert(bank);
if slot == saved_slot {
// Find the relevant snapshot storages
- let snapshot_storage_files: HashSet<_> = bank_forks[slot]
+ let snapshot_storage_files: HashSet<_> = bank_forks
+ .read()
+ .unwrap()
+ .get(slot)
+ .unwrap()
.get_snapshot_storages(None)
.into_iter()
.map(|s| s.get_path())
@@ -585,24 +604,31 @@ fn test_slots_to_snapshot(snapshot_version: SnapshotVersion, cluster_type: Clust
for add_root_interval in &[1, 3, 9] {
let (snapshot_sender, _snapshot_receiver) = unbounded();
// Make sure this test never clears bank.slots_since_snapshot
- let mut snapshot_test_config = SnapshotTestConfig::new(
+ let snapshot_test_config = SnapshotTestConfig::new(
snapshot_version,
cluster_type,
(*add_root_interval * num_set_roots * 2) as Slot,
(*add_root_interval * num_set_roots * 2) as Slot,
DISABLED_SNAPSHOT_ARCHIVE_INTERVAL,
);
- let mut current_bank = snapshot_test_config.bank_forks[0].clone();
+ let bank_forks = snapshot_test_config.bank_forks.clone();
+ let bank_forks_r = bank_forks.read().unwrap();
+ let mut current_bank = bank_forks_r[0].clone();
+ drop(bank_forks_r);
let request_sender = AbsRequestSender::new(snapshot_sender);
for _ in 0..num_set_roots {
for _ in 0..*add_root_interval {
let new_slot = current_bank.slot() + 1;
let new_bank = Bank::new_from_parent(current_bank, &Pubkey::default(), new_slot);
- snapshot_test_config.bank_forks.insert(new_bank);
- current_bank = snapshot_test_config.bank_forks[new_slot].clone();
+ current_bank = bank_forks.write().unwrap().insert(new_bank).clone();
}
- snapshot_test_config
- .bank_forks
+ bank_forks
+ .read()
+ .unwrap()
+ .prune_program_cache(current_bank.slot());
+ bank_forks
+ .write()
+ .unwrap()
.set_root(current_bank.slot(), &request_sender, None);
// Since the accounts background services are not runnning, EpochAccountsHash
@@ -628,10 +654,10 @@ fn test_slots_to_snapshot(snapshot_version: SnapshotVersion, cluster_type: Clust
let expected_slots_to_snapshot =
num_old_slots as u64..=num_set_roots as u64 * *add_root_interval as u64;
- let slots_to_snapshot = snapshot_test_config
- .bank_forks
- .get(snapshot_test_config.bank_forks.root())
+ let slots_to_snapshot = bank_forks
+ .read()
.unwrap()
+ .root_bank()
.status_cache
.read()
.unwrap()
@@ -703,7 +729,7 @@ fn test_bank_forks_incremental_snapshot(
info!("Running bank forks incremental snapshot test, full snapshot interval: {} slots, incremental snapshot interval: {} slots, last slot: {}, set root interval: {} slots",
FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS, INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS, LAST_SLOT, SET_ROOT_INTERVAL);
- let mut snapshot_test_config = SnapshotTestConfig::new(
+ let snapshot_test_config = SnapshotTestConfig::new(
snapshot_version,
cluster_type,
SET_ROOT_INTERVAL,
@@ -713,7 +739,7 @@ fn test_bank_forks_incremental_snapshot(
trace!("SnapshotTestConfig:\naccounts_dir: {}\nbank_snapshots_dir: {}\nfull_snapshot_archives_dir: {}\nincremental_snapshot_archives_dir: {}",
snapshot_test_config.accounts_dir.display(), snapshot_test_config.bank_snapshots_dir.path().display(), snapshot_test_config.full_snapshot_archives_dir.path().display(), snapshot_test_config.incremental_snapshot_archives_dir.path().display());
- let bank_forks = &mut snapshot_test_config.bank_forks;
+ let bank_forks = snapshot_test_config.bank_forks.clone();
let mint_keypair = &snapshot_test_config.genesis_config_info.mint_keypair;
let (accounts_package_sender, _accounts_package_receiver) = crossbeam_channel::unbounded();
@@ -730,8 +756,8 @@ fn test_bank_forks_incremental_snapshot(
for slot in 1..=LAST_SLOT {
// Make a new bank and perform some transactions
let bank = {
- let bank =
- Bank::new_from_parent(bank_forks[slot - 1].clone(), &Pubkey::default(), slot);
+ let parent = bank_forks.read().unwrap().get(slot - 1).unwrap();
+ let bank = Bank::new_from_parent(parent, &Pubkey::default(), slot);
let key = solana_sdk::pubkey::new_rand();
let tx = system_transaction::transfer(mint_keypair, &key, 1, bank.last_blockhash());
@@ -745,7 +771,7 @@ fn test_bank_forks_incremental_snapshot(
bank.register_tick(&Hash::new_unique());
}
- bank_forks.insert(bank)
+ bank_forks.write().unwrap().insert(bank)
};
// Set root to make sure we don't end up with too many account storage entries
@@ -753,7 +779,11 @@ fn test_bank_forks_incremental_snapshot(
// kick in
if slot % SET_ROOT_INTERVAL == 0 {
// set_root sends a snapshot request
- bank_forks.set_root(bank.slot(), &request_sender, None);
+ bank_forks.read().unwrap().prune_program_cache(bank.slot());
+ bank_forks
+ .write()
+ .unwrap()
+ .set_root(bank.slot(), &request_sender, None);
snapshot_request_handler.handle_snapshot_requests(
false,
0,
@@ -893,6 +923,7 @@ fn restore_from_snapshots_and_check_banks_are_equal(
false,
false,
false,
+ false,
Some(ACCOUNTS_DB_CONFIG_FOR_TESTING),
None,
Arc::default(),
@@ -962,7 +993,7 @@ fn test_snapshots_with_background_services(
let (accounts_package_sender, accounts_package_receiver) = unbounded();
let (snapshot_package_sender, snapshot_package_receiver) = unbounded();
- let bank_forks = Arc::new(RwLock::new(snapshot_test_config.bank_forks));
+ let bank_forks = snapshot_test_config.bank_forks.clone();
bank_forks
.read()
.unwrap()
@@ -1113,6 +1144,7 @@ fn test_snapshots_with_background_services(
false,
false,
false,
+ false,
Some(ACCOUNTS_DB_CONFIG_FOR_TESTING),
None,
exit.clone(),
diff --git a/cost-model/src/block_cost_limits.rs b/cost-model/src/block_cost_limits.rs
index 328d89cd041..b04f289e055 100644
--- a/cost-model/src/block_cost_limits.rs
+++ b/cost-model/src/block_cost_limits.rs
@@ -24,6 +24,10 @@ pub const MAX_CONCURRENCY: u64 = 4;
pub const COMPUTE_UNIT_TO_US_RATIO: u64 = 30;
/// Number of compute units for one signature verification.
pub const SIGNATURE_COST: u64 = COMPUTE_UNIT_TO_US_RATIO * 24;
+/// Number of compute units for one secp256k1 signature verification.
+pub const SECP256K1_VERIFY_COST: u64 = COMPUTE_UNIT_TO_US_RATIO * 223;
+/// Number of compute units for one ed25519 signature verification.
+pub const ED25519_VERIFY_COST: u64 = COMPUTE_UNIT_TO_US_RATIO * 76;
/// Number of compute units for one write lock
pub const WRITE_LOCK_UNITS: u64 = COMPUTE_UNIT_TO_US_RATIO * 10;
/// Number of data bytes per compute units
@@ -43,8 +47,8 @@ lazy_static! {
(bpf_loader::id(), solana_bpf_loader_program::DEFAULT_LOADER_COMPUTE_UNITS),
(loader_v4::id(), solana_loader_v4_program::DEFAULT_COMPUTE_UNITS),
// Note: These are precompile, run directly in bank during sanitizing;
- (secp256k1_program::id(), COMPUTE_UNIT_TO_US_RATIO * 24),
- (ed25519_program::id(), COMPUTE_UNIT_TO_US_RATIO * 24),
+ (secp256k1_program::id(), 0),
+ (ed25519_program::id(), 0),
]
.iter()
.cloned()
diff --git a/cost-model/src/cost_model.rs b/cost-model/src/cost_model.rs
index 0e8d6954202..d44d6550dc6 100644
--- a/cost-model/src/cost_model.rs
+++ b/cost-model/src/cost_model.rs
@@ -43,7 +43,7 @@ impl CostModel {
} else {
let mut tx_cost = UsageCostDetails::new_with_default_capacity();
- tx_cost.signature_cost = Self::get_signature_cost(transaction);
+ Self::get_signature_cost(&mut tx_cost, transaction);
Self::get_write_lock_cost(&mut tx_cost, transaction);
Self::get_transaction_cost(&mut tx_cost, transaction, feature_set);
tx_cost.account_data_size = Self::calculate_account_data_size(transaction);
@@ -69,8 +69,26 @@ impl CostModel {
)
}
- fn get_signature_cost(transaction: &SanitizedTransaction) -> u64 {
- transaction.signatures().len() as u64 * SIGNATURE_COST
+ fn get_signature_cost(tx_cost: &mut UsageCostDetails, transaction: &SanitizedTransaction) {
+ let signatures_count_detail = transaction.message().get_signature_details();
+ tx_cost.num_transaction_signatures = signatures_count_detail.num_transaction_signatures();
+ tx_cost.num_secp256k1_instruction_signatures =
+ signatures_count_detail.num_secp256k1_instruction_signatures();
+ tx_cost.num_ed25519_instruction_signatures =
+ signatures_count_detail.num_ed25519_instruction_signatures();
+ tx_cost.signature_cost = signatures_count_detail
+ .num_transaction_signatures()
+ .saturating_mul(SIGNATURE_COST)
+ .saturating_add(
+ signatures_count_detail
+ .num_secp256k1_instruction_signatures()
+ .saturating_mul(SECP256K1_VERIFY_COST),
+ )
+ .saturating_add(
+ signatures_count_detail
+ .num_ed25519_instruction_signatures()
+ .saturating_mul(ED25519_VERIFY_COST),
+ );
}
fn get_writable_accounts(transaction: &SanitizedTransaction) -> Vec {
diff --git a/cost-model/src/cost_tracker.rs b/cost-model/src/cost_tracker.rs
index e4f1b917d74..33b0172eacd 100644
--- a/cost-model/src/cost_tracker.rs
+++ b/cost-model/src/cost_tracker.rs
@@ -62,6 +62,9 @@ pub struct CostTracker {
/// The amount of total account data size remaining. If `Some`, then do not add transactions
/// that would cause `account_data_size` to exceed this limit.
account_data_size_limit: Option,
+ transaction_signature_count: u64,
+ secp256k1_instruction_signature_count: u64,
+ ed25519_instruction_signature_count: u64,
}
impl Default for CostTracker {
@@ -82,6 +85,9 @@ impl Default for CostTracker {
transaction_count: 0,
account_data_size: 0,
account_data_size_limit: None,
+ transaction_signature_count: 0,
+ secp256k1_instruction_signature_count: 0,
+ ed25519_instruction_signature_count: 0,
}
}
}
@@ -167,6 +173,21 @@ impl CostTracker {
("costliest_account", costliest_account.to_string(), String),
("costliest_account_cost", costliest_account_cost as i64, i64),
("account_data_size", self.account_data_size, i64),
+ (
+ "transaction_signature_count",
+ self.transaction_signature_count,
+ i64
+ ),
+ (
+ "secp256k1_instruction_signature_count",
+ self.secp256k1_instruction_signature_count,
+ i64
+ ),
+ (
+ "ed25519_instruction_signature_count",
+ self.ed25519_instruction_signature_count,
+ i64
+ ),
);
}
@@ -186,7 +207,9 @@ impl CostTracker {
if self.vote_cost.saturating_add(cost) > self.vote_cost_limit {
return Err(CostTrackerError::WouldExceedVoteMaxLimit);
}
- } else if self.block_cost.saturating_add(cost) > self.block_cost_limit {
+ }
+
+ if self.block_cost.saturating_add(cost) > self.block_cost_limit {
// check against the total package cost
return Err(CostTrackerError::WouldExceedBlockMaxLimit);
}
@@ -232,6 +255,18 @@ impl CostTracker {
self.add_transaction_execution_cost(tx_cost, tx_cost.sum());
saturating_add_assign!(self.account_data_size, tx_cost.account_data_size());
saturating_add_assign!(self.transaction_count, 1);
+ saturating_add_assign!(
+ self.transaction_signature_count,
+ tx_cost.num_transaction_signatures()
+ );
+ saturating_add_assign!(
+ self.secp256k1_instruction_signature_count,
+ tx_cost.num_secp256k1_instruction_signatures()
+ );
+ saturating_add_assign!(
+ self.ed25519_instruction_signature_count,
+ tx_cost.num_ed25519_instruction_signatures()
+ );
}
fn remove_transaction_cost(&mut self, tx_cost: &TransactionCost) {
@@ -241,6 +276,15 @@ impl CostTracker {
.account_data_size
.saturating_sub(tx_cost.account_data_size());
self.transaction_count = self.transaction_count.saturating_sub(1);
+ self.transaction_signature_count = self
+ .transaction_signature_count
+ .saturating_sub(tx_cost.num_transaction_signatures());
+ self.secp256k1_instruction_signature_count = self
+ .secp256k1_instruction_signature_count
+ .saturating_sub(tx_cost.num_secp256k1_instruction_signatures());
+ self.ed25519_instruction_signature_count = self
+ .ed25519_instruction_signature_count
+ .saturating_sub(tx_cost.num_ed25519_instruction_signatures());
}
/// Apply additional actual execution units to cost_tracker
diff --git a/cost-model/src/transaction_cost.rs b/cost-model/src/transaction_cost.rs
index e765eee3bc7..170be03e037 100644
--- a/cost-model/src/transaction_cost.rs
+++ b/cost-model/src/transaction_cost.rs
@@ -87,6 +87,27 @@ impl TransactionCost {
Self::Transaction(usage_cost) => &usage_cost.writable_accounts,
}
}
+
+ pub fn num_transaction_signatures(&self) -> u64 {
+ match self {
+ Self::SimpleVote { .. } => 1,
+ Self::Transaction(usage_cost) => usage_cost.num_transaction_signatures,
+ }
+ }
+
+ pub fn num_secp256k1_instruction_signatures(&self) -> u64 {
+ match self {
+ Self::SimpleVote { .. } => 0,
+ Self::Transaction(usage_cost) => usage_cost.num_secp256k1_instruction_signatures,
+ }
+ }
+
+ pub fn num_ed25519_instruction_signatures(&self) -> u64 {
+ match self {
+ Self::SimpleVote { .. } => 0,
+ Self::Transaction(usage_cost) => usage_cost.num_ed25519_instruction_signatures,
+ }
+ }
}
const MAX_WRITABLE_ACCOUNTS: usize = 256;
@@ -102,6 +123,9 @@ pub struct UsageCostDetails {
pub bpf_execution_cost: u64,
pub loaded_accounts_data_size_cost: u64,
pub account_data_size: u64,
+ pub num_transaction_signatures: u64,
+ pub num_secp256k1_instruction_signatures: u64,
+ pub num_ed25519_instruction_signatures: u64,
}
impl Default for UsageCostDetails {
@@ -115,6 +139,9 @@ impl Default for UsageCostDetails {
bpf_execution_cost: 0u64,
loaded_accounts_data_size_cost: 0u64,
account_data_size: 0u64,
+ num_transaction_signatures: 0u64,
+ num_secp256k1_instruction_signatures: 0u64,
+ num_ed25519_instruction_signatures: 0u64,
}
}
}
@@ -133,6 +160,10 @@ impl PartialEq for UsageCostDetails {
&& self.bpf_execution_cost == other.bpf_execution_cost
&& self.loaded_accounts_data_size_cost == other.loaded_accounts_data_size_cost
&& self.account_data_size == other.account_data_size
+ && self.num_transaction_signatures == other.num_transaction_signatures
+ && self.num_secp256k1_instruction_signatures
+ == other.num_secp256k1_instruction_signatures
+ && self.num_ed25519_instruction_signatures == other.num_ed25519_instruction_signatures
&& to_hash_set(&self.writable_accounts) == to_hash_set(&other.writable_accounts)
}
}
diff --git a/docs/src/api/http.md b/docs/src/api/http.md
index 63163fbfa4c..9edf2c792cd 100644
--- a/docs/src/api/http.md
+++ b/docs/src/api/http.md
@@ -154,13 +154,11 @@ Some methods support providing a `filters` object to enable pre-filtering the da
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" based on the following conditions:
+"ok", "behind" or "unknown":
-1. If one or more `--known-validator` arguments are provided to `solana-validator` - "ok" is returned
- when the node has within `HEALTH_CHECK_SLOT_DISTANCE` slots of the highest
- known validator, otherwise "behind". "unknown" is returned when no slot
- information from known validators is not yet available.
-2. "ok" is always returned if no known validators are provided.
+- `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
diff --git a/docs/src/api/methods/_getHealth.mdx b/docs/src/api/methods/_getHealth.mdx
index 482a2ff62a0..ceb30cc40fa 100644
--- a/docs/src/api/methods/_getHealth.mdx
+++ b/docs/src/api/methods/_getHealth.mdx
@@ -12,13 +12,8 @@ import {
## getHealth
-Returns the current health of the node.
-
-:::caution
-If one or more `--known-validator` arguments are provided to `solana-validator` - "ok" is returned
-when the node has within `HEALTH_CHECK_SLOT_DISTANCE` slots of the highest known validator,
-otherwise an error is returned. "ok" is always returned if no known validators are provided.
-:::
+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.
diff --git a/docs/src/cli/install-solana-cli-tools.md b/docs/src/cli/install-solana-cli-tools.md
index 26a4ede5af6..db0b30b607e 100644
--- a/docs/src/cli/install-solana-cli-tools.md
+++ b/docs/src/cli/install-solana-cli-tools.md
@@ -54,7 +54,7 @@ Please update your PATH environment variable to include the solana programs:
solana --version
```
-- After a successful install, `solana-install update` may be used to easily
+- After a successful install, `agave-install update` may be used to easily
update the Solana software to a newer version at any time.
---
@@ -72,7 +72,7 @@ solana --version
installer into a temporary directory:
```bash
-cmd /c "curl https://release.solana.com/LATEST_SOLANA_RELEASE_VERSION/solana-install-init-x86_64-pc-windows-msvc.exe --output C:\solana-install-tmp\solana-install-init.exe --create-dirs"
+cmd /c "curl https://release.solana.com/LATEST_SOLANA_RELEASE_VERSION/agave-install-init-x86_64-pc-windows-msvc.exe --output C:\agave-install-tmp\agave-install-init.exe --create-dirs"
```
- Copy and paste the following command, then press Enter to install the latest
@@ -80,7 +80,7 @@ cmd /c "curl https://release.solana.com/LATEST_SOLANA_RELEASE_VERSION/solana-ins
to allow the program to run.
```bash
-C:\solana-install-tmp\solana-install-init.exe LATEST_SOLANA_RELEASE_VERSION
+C:\agave-install-tmp\agave-install-init.exe LATEST_SOLANA_RELEASE_VERSION
```
- When the installer is finished, press Enter.
@@ -95,12 +95,12 @@ C:\solana-install-tmp\solana-install-init.exe LATEST_SOLANA_RELEASE_VERSION
solana --version
```
-- After a successful install, `solana-install update` may be used to easily
+- After a successful install, `agave-install update` may be used to easily
update the Solana software to a newer version at any time.
## Download Prebuilt Binaries
-If you would rather not use `solana-install` to manage the install, you can
+If you would rather not use `agave-install` to manage the install, you can
manually download and install the binaries.
### Linux
@@ -161,7 +161,7 @@ You can then run the following command to obtain the same result as with
prebuilt binaries:
```bash
-solana-install init
+agave-install init
```
## Use Homebrew
diff --git a/docs/src/cluster/bench-tps.md b/docs/src/cluster/bench-tps.md
index d913f9e5f16..35978cdd096 100644
--- a/docs/src/cluster/bench-tps.md
+++ b/docs/src/cluster/bench-tps.md
@@ -108,7 +108,7 @@ For example
Generally we are using `debug` for infrequent debug messages, `trace` for potentially frequent messages and `info` for performance-related logging.
-You can also attach to a running process with GDB. The leader's process is named _solana-validator_:
+You can also attach to a running process with GDB. The leader's process is named _agave-validator_:
```bash
sudo gdb
diff --git a/docs/src/clusters.md b/docs/src/clusters.md
index 5d59e7ea6cc..08102c68a8a 100644
--- a/docs/src/clusters.md
+++ b/docs/src/clusters.md
@@ -39,10 +39,10 @@ export SOLANA_METRICS_CONFIG="host=https://metrics.solana.com:8086,db=devnet,u=s
solana config set --url https://api.devnet.solana.com
```
-##### Example `solana-validator` command-line
+##### Example `agave-validator` command-line
```bash
-$ solana-validator \
+$ agave-validator \
--identity validator-keypair.json \
--vote-account vote-account-keypair.json \
--known-validator dv1ZAGvdsz5hHLwWXsVnM94hWf1pjbKVau1QVkaMJ92 \
@@ -91,10 +91,10 @@ export SOLANA_METRICS_CONFIG="host=https://metrics.solana.com:8086,db=tds,u=test
solana config set --url https://api.testnet.solana.com
```
-##### Example `solana-validator` command-line
+##### Example `agave-validator` command-line
```bash
-$ solana-validator \
+$ agave-validator \
--identity validator-keypair.json \
--vote-account vote-account-keypair.json \
--known-validator 5D1fNXzvv5NjV1ysLjirC4WY92RNsVH18vjmcszZd8on \
@@ -143,10 +143,10 @@ export SOLANA_METRICS_CONFIG="host=https://metrics.solana.com:8086,db=mainnet-be
solana config set --url https://api.mainnet-beta.solana.com
```
-##### Example `solana-validator` command-line
+##### Example `agave-validator` command-line
```bash
-$ solana-validator \
+$ agave-validator \
--identity ~/validator-keypair.json \
--vote-account ~/vote-account-keypair.json \
--known-validator 7Np41oeYqPefeNQEHSv1UDhYrehxin3NStELsSKCT4K2 \
diff --git a/docs/src/developing/backwards-compatibility.md b/docs/src/developing/backwards-compatibility.md
index 4a3c60b8e12..0fdc388ea2d 100644
--- a/docs/src/developing/backwards-compatibility.md
+++ b/docs/src/developing/backwards-compatibility.md
@@ -76,7 +76,7 @@ Major releases:
- [`solana-program`](https://docs.rs/solana-program/) - Rust SDK for writing programs
- [`solana-client`](https://docs.rs/solana-client/) - Rust client for connecting to RPC API
- [`solana-cli-config`](https://docs.rs/solana-cli-config/) - Rust client for managing Solana CLI config files
-- [`solana-geyser-plugin-interface`](https://docs.rs/solana-geyser-plugin-interface/) - Rust interface for developing Solana Geyser plugins.
+- [`agave-geyser-plugin-interface`](https://docs.rs/agave-geyser-plugin-interface/) - Rust interface for developing Solana Geyser plugins.
Patch releases:
diff --git a/docs/src/developing/on-chain-programs/debugging.md b/docs/src/developing/on-chain-programs/debugging.md
index fdbb1aebaa8..700985f2ee9 100644
--- a/docs/src/developing/on-chain-programs/debugging.md
+++ b/docs/src/developing/on-chain-programs/debugging.md
@@ -113,15 +113,15 @@ To turn on SBF interpreter trace messages in a local cluster configure the
## 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`,
+be done using the `program run` subcommand of `agave-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
+The `agave-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
+is connected to `agave-ledger-tool` gdbserver, it can control
+execution of an on-chain program. Run `agave-ledger-tool program run
--help` for an example of specifying input data for parameters of the
program entrypoint function.
@@ -131,7 +131,7 @@ 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`
+To execute a program in debugger, run `agave-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
@@ -139,27 +139,27 @@ 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
+The command line for running `agave-ledger-tool` would be something like this
```
-solana-ledger-tool program run -l test-ledger -e debugger target/deploy/helloworld.so
+agave-ledger-tool program run -l test-ledger -e debugger target/deploy/helloworld.so
```
-Note that `solana-ledger-tool` always loads a ledger database. Most
+Note that `agave-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
+`agave-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
+In debugger mode `agave-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
+To connect to `agave-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
+to start `agave-ledger-tool`) run the command
```
solana-lldb
@@ -181,7 +181,7 @@ 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
+Now, connect to the gdb server that `agave-ledger-tool` implements, and
debug the program as usual. Enter the following command at lldb prompt
```
(lldb) gdb-remote 127.0.0.1:9001
@@ -230,13 +230,13 @@ First file is `tasks.json` with the following content
{
"label": "solana-debugger",
"type": "shell",
- "command": "solana-ledger-tool program run -l test-ledger -e debugger ${workspaceFolder}/target/deploy/helloworld.so"
+ "command": "agave-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.
+utility. The second task is to run `agave-ledger-tool program run` in debugger mode.
Another file is `launch.json` with the following content
```
@@ -254,12 +254,12 @@ Another file is `launch.json` with the following content
}
```
This file specifies how to run debugger and to connect it to the gdb
-server implemented by `solana-ledger-tool`.
+server implemented by `agave-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
+VSCode. When `agave-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
diff --git a/docs/src/developing/on-chain-programs/deploying.md b/docs/src/developing/on-chain-programs/deploying.md
index 2f0d095444d..111ee98f8b7 100644
--- a/docs/src/developing/on-chain-programs/deploying.md
+++ b/docs/src/developing/on-chain-programs/deploying.md
@@ -56,7 +56,7 @@ As a data point of the number of accounts and potential data stored on-chain, be
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)_
+> _Note: this data was pulled with a modified `agave-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
diff --git a/docs/src/developing/plugins/geyser-plugins.md b/docs/src/developing/plugins/geyser-plugins.md
index 3ea07473a61..41e1b655e94 100644
--- a/docs/src/developing/plugins/geyser-plugins.md
+++ b/docs/src/developing/plugins/geyser-plugins.md
@@ -22,20 +22,20 @@ implementation for the PostgreSQL database.
### Important Crates:
-- [`solana-geyser-plugin-interface`] — This crate defines the plugin
+- [`agave-geyser-plugin-interface`] — This crate defines the plugin
interfaces.
- [`solana-accountsdb-plugin-postgres`] — The crate for the referential
plugin implementation for the PostgreSQL database.
-[`solana-geyser-plugin-interface`]: https://docs.rs/solana-geyser-plugin-interface
+[`agave-geyser-plugin-interface`]: https://docs.rs/agave-geyser-plugin-interface
[`solana-accountsdb-plugin-postgres`]: https://docs.rs/solana-accountsdb-plugin-postgres
[`solana-sdk`]: https://docs.rs/solana-sdk
[`solana-transaction-status`]: https://docs.rs/solana-transaction-status
## The Plugin Interface
-The Plugin interface is declared in [`solana-geyser-plugin-interface`]. It
+The Plugin interface is declared in [`agave-geyser-plugin-interface`]. It
is defined by the trait `GeyserPlugin`. The plugin should implement the
trait and expose a "C" function `_create_plugin` to return the pointer to this
trait. For example, in the referential implementation, the following code
@@ -164,7 +164,7 @@ please refer to [`solana-sdk`] and [`solana-transaction-status`]
The `slot` points to the slot the transaction is executed at.
For more details, please refer to the Rust documentation in
-[`solana-geyser-plugin-interface`].
+[`agave-geyser-plugin-interface`].
## Example PostgreSQL Plugin
diff --git a/docs/src/getstarted/local.md b/docs/src/getstarted/local.md
index 3a4358cac20..580c335749b 100644
--- a/docs/src/getstarted/local.md
+++ b/docs/src/getstarted/local.md
@@ -48,7 +48,7 @@ Confirm you have the desired version of `solana` installed by running:
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.
+After a successful install, `agave-install update` may be used to easily update the Solana software to a newer version at any time.
@@ -70,7 +70,7 @@ After a successful install, `solana-install update` may be used to easily update
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"
+cmd /c "curl https://release.solana.com/stable/agave-install-init-x86_64-pc-windows-msvc.exe --output C:\agave-install-tmp\agave-install-init.exe --create-dirs"
```
- Copy and paste the following command, then press Enter to install the latest
@@ -78,7 +78,7 @@ cmd /c "curl https://release.solana.com/stable/solana-install-init-x86_64-pc-win
to allow the program to run.
```bash
-C:\solana-install-tmp\solana-install-init.exe stable
+C:\agave-install-tmp\agave-install-init.exe stable
```
- When the installer is finished, press Enter.
@@ -91,7 +91,7 @@ C:\solana-install-tmp\solana-install-init.exe stable
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.
+After a successful install, `agave-install update` may be used to easily update the Solana software to a newer version at any time.
diff --git a/docs/src/implemented-proposals/installer.md b/docs/src/implemented-proposals/installer.md
index a3ad797171c..c052aa7b4e5 100644
--- a/docs/src/implemented-proposals/installer.md
+++ b/docs/src/implemented-proposals/installer.md
@@ -13,16 +13,16 @@ This document proposes an easy to use software install and updater that can be u
The easiest install method for supported platforms:
```bash
-$ curl -sSf https://raw.githubusercontent.com/solana-labs/solana/v1.0.0/install/solana-install-init.sh | sh
+$ curl -sSf https://raw.githubusercontent.com/solana-labs/solana/v1.0.0/install/agave-install-init.sh | sh
```
-This script will check github for the latest tagged release and download and run the `solana-install-init` binary from there.
+This script will check github for the latest tagged release and download and run the `agave-install-init` binary from there.
If additional arguments need to be specified during the installation, the following shell syntax is used:
```bash
-$ init_args=.... # arguments for `solana-install-init ...`
-$ curl -sSf https://raw.githubusercontent.com/solana-labs/solana/v1.0.0/install/solana-install-init.sh | sh -s - ${init_args}
+$ init_args=.... # arguments for `agave-install-init ...`
+$ curl -sSf https://raw.githubusercontent.com/solana-labs/solana/v1.0.0/install/agave-install-init.sh | sh -s - ${init_args}
```
### Fetch and run a pre-built installer from a Github release
@@ -30,9 +30,9 @@ $ curl -sSf https://raw.githubusercontent.com/solana-labs/solana/v1.0.0/install/
With a well-known release URL, a pre-built binary can be obtained for supported platforms:
```bash
-$ curl -o solana-install-init https://github.com/solana-labs/solana/releases/download/v1.0.0/solana-install-init-x86_64-apple-darwin
-$ chmod +x ./solana-install-init
-$ ./solana-install-init --help
+$ curl -o agave-install-init https://github.com/solana-labs/solana/releases/download/v1.0.0/agave-install-init-x86_64-apple-darwin
+$ chmod +x ./agave-install-init
+$ ./agave-install-init --help
```
### Build and run the installer from source
@@ -51,16 +51,16 @@ Given a solana release tarball \(as created by `ci/publish-tarball.sh`\) that ha
```bash
$ solana-keygen new -o update-manifest.json # <-- only generated once, the public key is shared with users
-$ solana-install deploy http://example.com/path/to/solana-release.tar.bz2 update-manifest.json
+$ agave-install deploy http://example.com/path/to/solana-release.tar.bz2 update-manifest.json
```
### Run a validator node that auto updates itself
```bash
-$ solana-install init --pubkey 92DMonmBYXwEMHJ99c9ceRSpAmk9v6i3RdvDdXaVcrfj # <-- pubkey is obtained from whoever is deploying the updates
-$ export PATH=~/.local/share/solana-install/bin:$PATH
+$ agave-install init --pubkey 92DMonmBYXwEMHJ99c9ceRSpAmk9v6i3RdvDdXaVcrfj # <-- pubkey is obtained from whoever is deploying the updates
+$ export PATH=~/.local/share/agave-install/bin:$PATH
$ solana-keygen ... # <-- runs the latest solana-keygen
-$ solana-install run solana-validator ... # <-- runs a validator, restarting it as necessary when an update is applied
+$ agave-install run agave-validator ... # <-- runs a validator, restarting it as necessary when an update is applied
```
## On-chain Update Manifest
@@ -87,9 +87,9 @@ pub struct SignedUpdateManifest {
}
```
-Note that the `manifest` field itself contains a corresponding signature \(`manifest_signature`\) to guard against man-in-the-middle attacks between the `solana-install` tool and the solana cluster RPC API.
+Note that the `manifest` field itself contains a corresponding signature \(`manifest_signature`\) to guard against man-in-the-middle attacks between the `agave-install` tool and the solana cluster RPC API.
-To guard against rollback attacks, `solana-install` will refuse to install an update with an older `timestamp_secs` than what is currently installed.
+To guard against rollback attacks, `agave-install` will refuse to install an update with an older `timestamp_secs` than what is currently installed.
## Release Archive Contents
@@ -101,17 +101,17 @@ A release archive is expected to be a tar file compressed with bzip2 with the fo
- `/bin/` -- directory containing available programs in the release.
- `solana-install` will symlink this directory to
+ `agave-install` will symlink this directory to
- `~/.local/share/solana-install/bin` for use by the `PATH` environment
+ `~/.local/share/agave-install/bin` for use by the `PATH` environment
variable.
- `...` -- any additional files and directories are permitted
-## solana-install Tool
+## agave-install Tool
-The `solana-install` tool is used by the user to install and update their cluster software.
+The `agave-install` tool is used by the user to install and update their cluster software.
It manages the following files and directories in the user's home directory:
@@ -122,11 +122,11 @@ It manages the following files and directories in the user's home directory:
### Command-line Interface
```text
-solana-install 0.16.0
+agave-install 0.16.0
The solana cluster software installer
USAGE:
- solana-install [OPTIONS]
+ agave-install [OPTIONS]
FLAGS:
-h, --help Prints help information
@@ -145,11 +145,11 @@ SUBCOMMANDS:
```
```text
-solana-install-init
+agave-install-init
initializes a new installation
USAGE:
- solana-install init [OPTIONS]
+ agave-install init [OPTIONS]
FLAGS:
-h, --help Prints help information
@@ -161,11 +161,11 @@ OPTIONS:
```
```text
-solana-install info
+agave-install info
displays information about the current installation
USAGE:
- solana-install info [FLAGS]
+ agave-install info [FLAGS]
FLAGS:
-h, --help Prints help information
@@ -173,11 +173,11 @@ FLAGS:
```
```text
-solana-install deploy
+agave-install deploy
deploys a new update
USAGE:
- solana-install deploy
+ agave-install deploy
FLAGS:
-h, --help Prints help information
@@ -188,22 +188,22 @@ ARGS:
```
```text
-solana-install update
+agave-install update
checks for an update, and if available downloads and applies it
USAGE:
- solana-install update
+ agave-install update
FLAGS:
-h, --help Prints help information
```
```text
-solana-install run
+agave-install run
Runs a program while periodically checking and applying software updates
USAGE:
- solana-install run [program_arguments]...
+ agave-install run [program_arguments]...
FLAGS:
-h, --help Prints help information
diff --git a/docs/src/implemented-proposals/rpc-transaction-history.md b/docs/src/implemented-proposals/rpc-transaction-history.md
index c8eb878eae4..d728254412b 100644
--- a/docs/src/implemented-proposals/rpc-transaction-history.md
+++ b/docs/src/implemented-proposals/rpc-transaction-history.md
@@ -68,7 +68,7 @@ results of BigTable queries more complicated but is not a significant issue.
## Data Population
The ongoing population of instance data will occur on an epoch cadence through the
-use of a new `solana-ledger-tool` command that will convert rocksdb data for a
+use of a new `agave-ledger-tool` command that will convert rocksdb data for a
given slot range into the instance schema.
The same process will be run once, manually, to backfill the existing ledger
diff --git a/docs/src/integrations/exchange.md b/docs/src/integrations/exchange.md
index 2e8d70f9cc6..9de6d517fd6 100644
--- a/docs/src/integrations/exchange.md
+++ b/docs/src/integrations/exchange.md
@@ -28,7 +28,7 @@ To run an api node:
2. Start the validator with at least the following parameters:
```bash
-solana-validator \
+agave-validator \
--ledger \
--identity \
--entrypoint \
@@ -44,14 +44,14 @@ solana-validator \
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)
+[Current parameters for Mainnet Beta](../clusters.md#example-agave-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
+`--limit-ledger-size` if desired. Check `agave-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).
@@ -70,16 +70,16 @@ 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
+[`agave-watchtower`](https://github.com/solana-labs/solana/blob/master/watchtower/README.md),
+which can monitor your validator and detect with the `agave-validator` process
is unhealthy. It can directly be configured to alert you via Slack, Telegram,
-Discord, or Twillio. For details, run `solana-watchtower --help`.
+Discord, or Twillio. For details, run `agave-watchtower --help`.
```bash
-solana-watchtower --validator-identity
+agave-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.
+> You can find more information about the [best practices for Solana Watchtower](../validator/best-practices/monitoring.md#agave-watchtower) here in the docs.
#### New Software Release Announcements
@@ -103,7 +103,7 @@ 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
+`agave-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
diff --git a/docs/src/integrations/retrying-transactions.md b/docs/src/integrations/retrying-transactions.md
index c2d7ff24be2..29cdeafa0c0 100644
--- a/docs/src/integrations/retrying-transactions.md
+++ b/docs/src/integrations/retrying-transactions.md
@@ -106,7 +106,7 @@ according to three ports:
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).
+[this excellent writeup by Jito Labs](https://jito-labs.medium.com/agave-validator-101-transaction-processing-90bcdc271143).
## How Transactions Get Dropped
diff --git a/docs/src/running-validator/restart-cluster.md b/docs/src/running-validator/restart-cluster.md
index 4039f69a6b4..4823ae2fd5c 100644
--- a/docs/src/running-validator/restart-cluster.md
+++ b/docs/src/running-validator/restart-cluster.md
@@ -5,7 +5,7 @@
In Solana 1.14 or greater, run the following command to output the latest
optimistically confirmed slot your validator observed:
```bash
-solana-ledger-tool -l ledger latest-optimistic-slots
+agave-ledger-tool -l ledger latest-optimistic-slots
```
In Solana 1.13 or less, the latest optimistically confirmed can be found by looking for the more recent occurrence of
@@ -28,11 +28,11 @@ instead.
### Step 4. Create a new snapshot for slot `SLOT_X` with a hard fork at slot `SLOT_X`
```bash
-$ solana-ledger-tool -l --snapshot-archive-path --incremental-snapshot-archive-path create-snapshot SLOT_X --hard-fork SLOT_X
+$ agave-ledger-tool -l --snapshot-archive-path --incremental-snapshot-archive-path create-snapshot SLOT_X --hard-fork SLOT_X
```
The snapshots directory should now contain the new snapshot.
-`solana-ledger-tool create-snapshot` will also output the new shred version, and bank hash value,
+`agave-ledger-tool create-snapshot` will also output the new shred version, and bank hash value,
call this NEW_SHRED_VERSION and NEW_BANK_HASH respectively.
Adjust your validator's arguments:
@@ -62,7 +62,7 @@ Post something like the following to #announcements (adjusting the text as appro
> 2. a. Preferred method, start from your local ledger with:
>
> ```bash
-> solana-validator
+> agave-validator
> --wait-for-supermajority SLOT_X # <-- NEW! IMPORTANT! REMOVE AFTER THIS RESTART
> --expected-bank-hash NEW_BANK_HASH # <-- NEW! IMPORTANT! REMOVE AFTER THIS RESTART
> --hard-fork SLOT_X # <-- NEW! IMPORTANT! REMOVE AFTER THIS RESTART
@@ -78,7 +78,7 @@ Post something like the following to #announcements (adjusting the text as appro
> b. If your validator doesn't have ledger up to slot SLOT_X or if you have deleted your ledger, have it instead download a snapshot with:
>
> ```bash
-> solana-validator
+> agave-validator
> --wait-for-supermajority SLOT_X # <-- NEW! IMPORTANT! REMOVE AFTER THIS RESTART
> --expected-bank-hash NEW_BANK_HASH # <-- NEW! IMPORTANT! REMOVE AFTER THIS RESTART
> --entrypoint entrypoint.testnet.solana.com:8001
@@ -89,7 +89,7 @@ Post something like the following to #announcements (adjusting the text as appro
> ... # <-- your other --identity/--vote-account/etc arguments
> ```
>
-> You can check for which slots your ledger has with: `solana-ledger-tool -l path/to/ledger bounds`
+> You can check for which slots your ledger has with: `agave-ledger-tool -l path/to/ledger bounds`
>
> 3. Wait until 80% of the stake comes online
>
@@ -116,7 +116,7 @@ and create a new snapshot with additional `--destake-vote-account `
arguments for each of the non-responsive validator's vote account address
```bash
-$ solana-ledger-tool -l ledger create-snapshot SLOT_X ledger --hard-fork SLOT_X \
+$ agave-ledger-tool -l ledger create-snapshot SLOT_X ledger --hard-fork SLOT_X \
--destake-vote-account \
--destake-vote-account \
.
diff --git a/docs/src/running-validator/validator-failover.md b/docs/src/running-validator/validator-failover.md
index 34968b73640..1329dd58b22 100644
--- a/docs/src/running-validator/validator-failover.md
+++ b/docs/src/running-validator/validator-failover.md
@@ -82,11 +82,11 @@ For more information on etcd TLS setup, please refer to
https://etcd.io/docs/v3.5/op-guide/security/#example-2-client-to-server-authentication-with-https-client-certificates
### Primary Validator
-The following additional `solana-validator` parameters are required to enable
+The following additional `agave-validator` parameters are required to enable
tower storage into etcd:
```
-solana-validator ... \
+agave-validator ... \
--tower-storage etcd \
--etcd-cacert-file certs/etcd-ca.pem \
--etcd-cert-file certs/validator.pem \
@@ -100,7 +100,7 @@ that your etcd endpoint remain accessible at all times.
### Secondary Validator
Configure the secondary validator like the primary with the exception of the
-following `solana-validator` command-line argument changes:
+following `agave-validator` command-line argument changes:
* Generate and use a secondary validator identity: `--identity secondary-validator-keypair.json`
* Add `--no-check-vote-account`
* Add `--authorized-voter validator-keypair.json` (where
@@ -111,8 +111,8 @@ When both validators are running normally and caught up to the cluster, a
failover from primary to secondary can be triggered by running the following
command on the secondary validator:
```bash
-$ solana-validator wait-for-restart-window --identity validator-keypair.json \
- && solana-validator set-identity validator-keypair.json
+$ agave-validator wait-for-restart-window --identity validator-keypair.json \
+ && agave-validator set-identity validator-keypair.json
```
The secondary validator will acquire a lock on the tower in etcd to ensure
@@ -128,7 +128,7 @@ exit. However if/when the secondary validator restarts, it will do so using the
secondary validator identity and thus the restart cycle is broken.
## Triggering a failover via monitoring
-Monitoring of your choosing can invoke the `solana-validator set-identity
+Monitoring of your choosing can invoke the `agave-validator set-identity
validator-keypair.json` command mentioned in the previous section.
It is not necessary to guarantee the primary validator has halted before failing
diff --git a/docs/src/running-validator/validator-stake.md b/docs/src/running-validator/validator-stake.md
index ae430ae9675..71c9cd21301 100644
--- a/docs/src/running-validator/validator-stake.md
+++ b/docs/src/running-validator/validator-stake.md
@@ -3,7 +3,7 @@ title: Staking
---
**By default your validator will have no stake.** This means it will be
-ineligible to become leader.
+ineligible to become leader, and unable to land votes.
## Monitoring Catch Up
@@ -55,8 +55,25 @@ but only one re-delegation is permitted per epoch:
solana delegate-stake ~/validator-stake-keypair.json ~/some-other-vote-account-keypair.json
```
-Assuming the node is voting, now you're up and running and generating validator
-rewards. Rewards are paid automatically on epoch boundaries.
+## 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.
+
+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`
+
+## 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.
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
@@ -76,21 +93,6 @@ before submitting a transaction.
Learn more about [transaction fees here](../implemented-proposals/transaction-fees.md).
-## 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.
-
-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`
-
## Monitor Your Staked Validator
Confirm your validator becomes a [leader](../terminology.md#leader)
diff --git a/docs/src/running-validator/validator-start.md b/docs/src/running-validator/validator-start.md
index d30533abd54..5a3f5ca3402 100644
--- a/docs/src/running-validator/validator-start.md
+++ b/docs/src/running-validator/validator-start.md
@@ -29,7 +29,7 @@ detail on cluster activity.
## Enabling CUDA
If your machine has a GPU with CUDA installed \(Linux-only currently\), include
-the `--cuda` argument to `solana-validator`.
+the `--cuda` argument to `agave-validator`.
When your validator is started look for the following log message to indicate
that CUDA is enabled: `"[ solana::validator] CUDA is enabled"`
@@ -44,7 +44,7 @@ the following commands.
#### **Optimize sysctl knobs**
```bash
-sudo bash -c "cat >/etc/sysctl.d/21-solana-validator.conf </etc/sysctl.d/21-agave-validator.conf <`
-argument to `solana-validator`. You can specify multiple ones by repeating the argument `--known-validator --known-validator `.
+argument to `agave-validator`. You can specify multiple ones by repeating the argument `--known-validator --known-validator `.
This has two effects, one is when the validator is booting with `--only-known-rpc`, it will only ask that set of
known nodes for downloading genesis and snapshot data. Another is that in combination with the `--halt-on-known-validators-accounts-hash-mismatch` option,
it will monitor the merkle root hash of the entire accounts state of other known nodes on gossip and if the hashes produce any mismatch,
@@ -274,13 +280,13 @@ account state divergence.
Connect to the cluster by running:
```bash
-solana-validator \
+agave-validator \
--identity ~/validator-keypair.json \
--vote-account ~/vote-account-keypair.json \
--rpc-port 8899 \
--entrypoint entrypoint.devnet.solana.com:8001 \
--limit-ledger-size \
- --log ~/solana-validator.log
+ --log ~/agave-validator.log
```
To force validator logging to the console add a `--log -` argument, otherwise
@@ -293,7 +299,7 @@ The ledger will be placed in the `ledger/` directory by default, use the
> [paper wallet seed phrase](../wallet-guide/paper-wallet.md)
> for your `--identity` and/or
> `--authorized-voter` keypairs. To use these, pass the respective argument as
-> `solana-validator --identity ASK ... --authorized-voter ASK ...`
+> `agave-validator --identity ASK ... --authorized-voter ASK ...`
> and you will be prompted to enter your seed phrases and optional passphrase.
Confirm your validator is connected to the network by opening a new terminal and
@@ -309,7 +315,7 @@ If your validator is connected, its public key and IP address will appear in the
By default the validator will dynamically select available network ports in the
8000-10000 range, and may be overridden with `--dynamic-port-range`. For
-example, `solana-validator --dynamic-port-range 11000-11020 ...` will restrict
+example, `agave-validator --dynamic-port-range 11000-11020 ...` will restrict
the validator to ports 11000-11020.
### Limiting ledger size to conserve disk space
@@ -363,8 +369,8 @@ WantedBy=multi-user.target
```
Now create `/home/sol/bin/validator.sh` to include the desired
-`solana-validator` command-line. Ensure that the 'exec' command is used to
-start the validator process (i.e. "exec solana-validator ..."). This is
+`agave-validator` command-line. Ensure that the 'exec' command is used to
+start the validator process (i.e. "exec agave-validator ..."). This is
important because without it, logrotate will end up killing the validator
every time the logs are rotated.
@@ -391,14 +397,14 @@ to be reverted and the issue reproduced before help can be provided.
#### Log rotation
-The validator log file, as specified by `--log ~/solana-validator.log`, can get
+The validator log file, as specified by `--log ~/agave-validator.log`, can get
very large over time and it's recommended that log rotation be configured.
The validator will re-open its log file when it receives the `USR1` signal, which is the
basic primitive that enables log rotation.
If the validator is being started by a wrapper shell script, it is important to
-launch the process with `exec` (`exec solana-validator ...`) when using logrotate.
+launch the process with `exec` (`exec agave-validator ...`) when using logrotate.
This will prevent the `USR1` signal from being sent to the script's process
instead of the validator's, which will kill them both.
@@ -406,13 +412,13 @@ instead of the validator's, which will kill them both.
An example setup for the `logrotate`, which assumes that the validator is
running as a systemd service called `sol.service` and writes a log file at
-/home/sol/solana-validator.log:
+/home/sol/agave-validator.log:
```bash
# Setup log rotation
cat > logrotate.sol <
@@ -72,14 +72,14 @@ Next, in your browser, go to `https://api.telegram.org/bot/getUp
The response should be in JSON. Search for the string `"chat":` in the JSON. The `id` value of that chat is your `TELEGRAM_CHAT_ID`. It will be a negative number like: `-781559558`. Remember to include the negative sign! If you cannot find `"chat":` in the JSON, then you may have to remove the bot from your chat group and add it again.
-With your Telegram chat id in hand, export the environment variable where you plan to run `solana-watchtower`:
+With your Telegram chat id in hand, export the environment variable where you plan to run `agave-watchtower`:
```
export TELEGRAM_CHAT_ID=
```
-#### Restart solana-watchtower
+#### Restart agave-watchtower
-Once your environment variables are set, restart `solana-watchtower`. You should see output about your validator.
+Once your environment variables are set, restart `agave-watchtower`. You should see output about your validator.
To test that your Telegram configuration is working properly, you could stop your validator briefly until it is labeled as delinquent. Up to a minute after the validator is delinquent, you should receive a message in the Telegram group from your bot. Start the validator again and verify that you get another message in your Telegram group from the bot. The message should say `all clear`.
\ No newline at end of file
diff --git a/docs/src/validator/best-practices/operations.md b/docs/src/validator/best-practices/operations.md
index 0588fc9ee90..7560f77994d 100644
--- a/docs/src/validator/best-practices/operations.md
+++ b/docs/src/validator/best-practices/operations.md
@@ -13,10 +13,10 @@ The Solana validator community holds regular educational workshops. You can watc
## 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.
+From within the Solana CLI, you can execute the `agave-validator` command with the `--help` flag to get a better understanding of the flags and sub commands available.
```
-solana-validator --help
+agave-validator --help
```
## Restarting your validator
@@ -31,10 +31,10 @@ 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:
+Assuming you are ready to restart, you may use the `agave-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
+agave-validator exit --help
```
## Upgrading
@@ -45,27 +45,27 @@ There are many ways to upgrade the [Solana software](../../cli/install-solana-cl
### 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.
+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 `agave-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
+### agave-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.
+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 `agave-install` command.
Assuming you want to install Solana version `1.14.17`, you would execute the following:
```
-solana-install init 1.14.17
+agave-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.
+This command downloads the executable for `1.14.17` and installs it into a `.local` directory. You can also look at `agave-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.
+For all install methods, the validator process will need to be restarted before the newly installed version is in use. Use `agave-validator exit` to restart your validator process.
### Verifying version
@@ -79,13 +79,13 @@ grep -B1 'Starting validator with'
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:
+To avoid downloading a snapshot on restart, add the following flag to the `agave-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.
+If you use this flag with the `agave-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
@@ -122,13 +122,13 @@ Once you have a local snapshot, you can restart your validator with the `--no-sn
## 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:
+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 `agave-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.
+> **Note** `agave-watchtower` can monitor for a minimum validator identity balance. See [monitoring best practices](./monitoring.md) for details.
## Withdrawing From The Vote Account
diff --git a/docs/src/validator/get-started/setup-a-validator.md b/docs/src/validator/get-started/setup-a-validator.md
index 6598400bda5..a745798cd23 100644
--- a/docs/src/validator/get-started/setup-a-validator.md
+++ b/docs/src/validator/get-started/setup-a-validator.md
@@ -245,7 +245,7 @@ Your system will need to be tuned in order to run properly. Your validator may n
#### **Optimize sysctl knobs**
```bash
-sudo bash -c "cat >/etc/sysctl.d/21-solana-validator.conf </etc/sysctl.d/21-agave-validator.conf < For more explanation on the flags used in the command, refer to the `solana-validator --help` command
+> For more explanation on the flags used in the command, refer to the `agave-validator --help` command
```
#!/bin/bash
-exec solana-validator \
+exec agave-validator \
--identity /home/sol/validator-keypair.json \
--known-validator 5D1fNXzvv5NjV1ysLjirC4WY92RNsVH18vjmcszZd8on \
--known-validator dDzy5SR3AXdYWVqbDEkVFdvSPCtS9ihF5kJkHCtXoFs \
@@ -67,4 +67,19 @@ The identities of the [known validators](../../running-validator/validator-start
Additional examples of other Solana cluster specific validator commands can be found on the [Clusters](../../clusters.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.
\ No newline at end of file
+Keep in mind, you will still need to customize these commands to operate as an RPC node, as well other operator specific configuration settings.
+
+## Account indexing
+
+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) --
+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.
diff --git a/dos/src/main.rs b/dos/src/main.rs
index 8e6c3c5b2b1..6a7968669f4 100644
--- a/dos/src/main.rs
+++ b/dos/src/main.rs
@@ -755,7 +755,7 @@ fn run_dos(
}
fn main() {
- solana_logger::setup_with_default("solana=info");
+ solana_logger::setup_with_default_filter();
let cmd_params = build_cli_parameters();
let (nodes, client) = if !cmd_params.skip_gossip {
diff --git a/faucet/src/bin/faucet.rs b/faucet/src/bin/faucet.rs
index 8e45ef98155..56cc7542623 100644
--- a/faucet/src/bin/faucet.rs
+++ b/faucet/src/bin/faucet.rs
@@ -19,7 +19,7 @@ use {
async fn main() {
let default_keypair = solana_cli_config::Config::default().keypair_path;
- solana_logger::setup_with_default("solana=info");
+ solana_logger::setup_with_default_filter();
solana_metrics::set_panic_hook("faucet", /*version:*/ None);
let matches = App::new(crate_name!())
.about(crate_description!())
diff --git a/frozen-abi/Cargo.toml b/frozen-abi/Cargo.toml
index 3121b6968eb..898b6d9b205 100644
--- a/frozen-abi/Cargo.toml
+++ b/frozen-abi/Cargo.toml
@@ -38,6 +38,7 @@ cc = { workspace = true, features = ["jobserver", "parallel"] }
[target.'cfg(not(target_os = "solana"))'.dev-dependencies]
solana-logger = { workspace = true }
+bitflags = { workspace = true }
[build-dependencies]
rustc_version = { workspace = true }
diff --git a/frozen-abi/src/abi_digester.rs b/frozen-abi/src/abi_digester.rs
index 0d0886daae7..b014efd2ba1 100644
--- a/frozen-abi/src/abi_digester.rs
+++ b/frozen-abi/src/abi_digester.rs
@@ -17,7 +17,7 @@ pub struct AbiDigester {
data_types: std::rc::Rc>>,
depth: usize,
for_enum: bool,
- opaque_scope: Option,
+ opaque_type_matcher: Option,
}
pub type DigestResult = Result;
@@ -70,7 +70,7 @@ impl AbiDigester {
data_types: std::rc::Rc::new(std::cell::RefCell::new(vec![])),
for_enum: false,
depth: 0,
- opaque_scope: None,
+ opaque_type_matcher: None,
}
}
@@ -81,16 +81,16 @@ impl AbiDigester {
data_types: self.data_types.clone(),
depth: self.depth,
for_enum: false,
- opaque_scope: self.opaque_scope.clone(),
+ opaque_type_matcher: self.opaque_type_matcher.clone(),
}
}
- pub fn create_new_opaque(&self, top_scope: &str) -> Self {
+ pub fn create_new_opaque(&self, type_matcher: &str) -> Self {
Self {
data_types: self.data_types.clone(),
depth: self.depth,
for_enum: false,
- opaque_scope: Some(top_scope.to_owned()),
+ opaque_type_matcher: Some(type_matcher.to_owned()),
}
}
@@ -103,7 +103,7 @@ impl AbiDigester {
data_types: self.data_types.clone(),
depth,
for_enum: false,
- opaque_scope: self.opaque_scope.clone(),
+ opaque_type_matcher: self.opaque_type_matcher.clone(),
})
}
@@ -116,15 +116,15 @@ impl AbiDigester {
data_types: self.data_types.clone(),
depth,
for_enum: true,
- opaque_scope: self.opaque_scope.clone(),
+ opaque_type_matcher: self.opaque_type_matcher.clone(),
})
}
pub fn digest_data(&mut self, value: &T) -> DigestResult {
let type_name = normalize_type_name(type_name::());
if type_name.ends_with("__SerializeWith")
- || (self.opaque_scope.is_some()
- && type_name.starts_with(self.opaque_scope.as_ref().unwrap()))
+ || (self.opaque_type_matcher.is_some()
+ && type_name.contains(self.opaque_type_matcher.as_ref().unwrap()))
{
// we can't use the AbiEnumVisitor trait for these cases.
value.serialize(self.create_new())
@@ -661,6 +661,34 @@ mod tests {
#[frozen_abi(digest = "9PMdHRb49BpkywrmPoJyZWMsEmf5E1xgmsFGkGmea5RW")]
type TestBitVec = bv::BitVec;
+ mod bitflags_abi {
+ use crate::abi_example::{AbiExample, EvenAsOpaque, IgnoreAsHelper};
+
+ bitflags::bitflags! {
+ #[frozen_abi(digest = "HhKNkaeAd7AohTb8S8sPKjAWwzxWY2DPz5FvkWmx5bSH")]
+ #[derive(Serialize, Deserialize)]
+ struct TestFlags: u8 {
+ const TestBit = 0b0000_0001;
+ }
+ }
+
+ impl AbiExample for TestFlags {
+ fn example() -> Self {
+ Self::empty()
+ }
+ }
+
+ impl IgnoreAsHelper for TestFlags {}
+ // This (EvenAsOpaque) marker trait is needed for bitflags-generated types because we can't
+ // impl AbiExample for its private type:
+ // thread '...TestFlags_frozen_abi...' panicked at ...:
+ // derive or implement AbiExample/AbiEnumVisitor for
+ // solana_frozen_abi::abi_digester::tests::_::InternalBitFlags
+ impl EvenAsOpaque for TestFlags {
+ const TYPE_NAME_MATCHER: &'static str = "::_::InternalBitFlags";
+ }
+ }
+
mod skip_should_be_same {
#[frozen_abi(digest = "4LbuvQLX78XPbm4hqqZcHFHpseDJcw4qZL9EUZXSi2Ss")]
#[derive(Serialize, AbiExample)]
@@ -691,4 +719,12 @@ mod tests {
Variant2(u8, u16, #[serde(skip)] u32),
}
}
+
+ #[frozen_abi(digest = "B1PcwZdUfGnxaRid9e6ZwkST3NZ2KUEYobA1DkxWrYLP")]
+ #[derive(Serialize, AbiExample)]
+ struct TestArcWeak(std::sync::Weak);
+
+ #[frozen_abi(digest = "4R8uCLR1BVU1aFgkSaNyKcFD1FeM6rGdsjbJBFpnqx4v")]
+ #[derive(Serialize, AbiExample)]
+ struct TestRcWeak(std::rc::Weak);
}
diff --git a/frozen-abi/src/abi_example.rs b/frozen-abi/src/abi_example.rs
index c7765c4a573..ab68c6ff25e 100644
--- a/frozen-abi/src/abi_example.rs
+++ b/frozen-abi/src/abi_example.rs
@@ -6,6 +6,24 @@ use {
std::any::type_name,
};
+// The most important trait for the abi digesting. This trait is used to create any complexities of
+// object graph to generate the abi digest. The frozen abi test harness calls T::example() to
+// instantiate the tested root type and traverses its fields recursively, abusing the
+// serde::serialize().
+//
+// This trait applicability is similar to the Default trait. That means all referenced types must
+// implement this trait. AbiExample is implemented for almost all common types in this file.
+//
+// When implementing AbiExample manually, you need to return a _minimally-populated_ value
+// from it to actually generate a meaningful digest. This impl semantics is unlike Default, which
+// usually returns something empty. See actual impls for inspiration.
+//
+// The requirement of AbiExample impls even applies to those types of `#[serde(skip)]`-ed fields.
+// That's because the abi digesting needs a properly initialized object to enter into the
+// serde::serialize() to begin with, even knowning they aren't used for serialization and thus abi
+// digest. Luckily, `#[serde(skip)]`-ed fields' AbiExample impls can just delegate to T::default(),
+// exploiting the nature of this artificial impl requirement as an exception from the usual
+// AbiExample semantics.
pub trait AbiExample: Sized {
fn example() -> Self;
}
@@ -137,25 +155,12 @@ tuple_example_impls! {
}
}
-// Source: https://github.com/rust-lang/rust/blob/ba18875557aabffe386a2534a1aa6118efb6ab88/src/libcore/array/mod.rs#L417
-macro_rules! array_example_impls {
- {$n:expr, $t:ident $($ts:ident)*} => {
- impl AbiExample for [T; $n] where T: AbiExample {
- fn example() -> Self {
- [$t::example(), $($ts::example()),*]
- }
- }
- array_example_impls!{($n - 1), $($ts)*}
- };
- {$n:expr,} => {
- impl AbiExample for [T; $n] {
- fn example() -> Self { [] }
- }
- };
+impl AbiExample for [T; N] {
+ fn example() -> Self {
+ std::array::from_fn(|_| T::example())
+ }
}
-array_example_impls! {32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
-
// Source: https://github.com/rust-lang/rust/blob/ba18875557aabffe386a2534a1aa6118efb6ab88/src/libcore/default.rs#L137
macro_rules! example_impls {
($t:ty, $v:expr) => {
@@ -232,7 +237,14 @@ impl AbiExample for BitVec {
}
impl IgnoreAsHelper for BitVec {}
-impl EvenAsOpaque for BitVec {}
+// This (EvenAsOpaque) marker trait is needed for BitVec because we can't impl AbiExample for its
+// private type:
+// thread '...TestBitVec_frozen_abi...' panicked at ...:
+// derive or implement AbiExample/AbiEnumVisitor for
+// bv::bit_vec::inner::Inner
+impl EvenAsOpaque for BitVec