Merge pull request #74 from 0g-wh/dev
Some checks failed
Continuous Integration (Commit) / lint (push) Has been cancelled

rebase to kava 0.27
This commit is contained in:
0g-wh 2024-10-14 15:27:58 +08:00 committed by GitHub
commit a1dc4a4a77
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
154 changed files with 27804 additions and 5458 deletions

View File

@ -11,5 +11,10 @@ docs/
networks/ networks/
scratch/ scratch/
# Ignore build cache directories to avoid
# errors when addings these to docker images
build/.cache
build/.golangci-lint
go.work go.work
go.work.sum go.work.sum

3
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1,3 @@
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
# Global rule:
* @rhuairahrighairidh @karzak @pirtleshell @drklee3 @nddeluca @DracoLi @evgeniy-scherbina @sesheffield @boodyvo @lbayas

View File

@ -83,6 +83,31 @@ TETHER_USDT_CONTRACT_DEPLOY=$(npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NA
TETHER_USDT_CONTRACT_ADDRESS=${TETHER_USDT_CONTRACT_DEPLOY: -42} TETHER_USDT_CONTRACT_ADDRESS=${TETHER_USDT_CONTRACT_DEPLOY: -42}
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$TETHER_USDT_CONTRACT_ADDRESS" 0x6767114FFAA17C6439D7AEA480738B982CE63A02 1000000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$TETHER_USDT_CONTRACT_ADDRESS" 0x6767114FFAA17C6439D7AEA480738B982CE63A02 1000000000000
# deploy and fund axlBNB ERC20 contract
AXL_BNB_CONTRACT_DEPLOY=$(npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" deploy-erc20 "axlBNB" axlBNB 18)
AXL_BNB_CONTRACT_ADDRESS=${AXL_BNB_CONTRACT_DEPLOY: -42}
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BNB_CONTRACT_ADDRESS" 0x6767114FFAA17C6439D7AEA480738B982CE63A02 1000000000000000000000
# deploy and fund axlBUSD ERC20 contract
AXL_BUSD_CONTRACT_DEPLOY=$(npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" deploy-erc20 "axlBUSD" axlBUSD 18)
AXL_BUSD_CONTRACT_ADDRESS=${AXL_BUSD_CONTRACT_DEPLOY: -42}
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BUSD_CONTRACT_ADDRESS" 0x6767114FFAA17C6439D7AEA480738B982CE63A02 1000000000000000000000
# deploy and fund axlXRPB ERC20 contract
AXL_XRPB_CONTRACT_DEPLOY=$(npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" deploy-erc20 "axlXRPB" axlXRPB 18)
AXL_XRPB_CONTRACT_ADDRESS=${AXL_XRPB_CONTRACT_DEPLOY: -42}
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_XRPB_CONTRACT_ADDRESS" 0x6767114FFAA17C6439D7AEA480738B982CE63A02 1000000000000000000000
# deploy and fund axlBTC ERC20 contract
AXL_BTCB_CONTRACT_DEPLOY=$(npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" deploy-erc20 "axlBTCB" axlBTCB 18)
AXL_BTCB_CONTRACT_ADDRESS=${AXL_BTCB_CONTRACT_DEPLOY: -42}
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BTCB_CONTRACT_ADDRESS" 0x6767114FFAA17C6439D7AEA480738B982CE63A02 1000000000000000000000
# deploy and fund native wBTC ERC20 contract
WBTC_CONTRACT_DEPLOY=$(npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" deploy-erc20 "wBTC" wBTC 8)
WBTC_CONTRACT_ADDRESS=${WBTC_CONTRACT_DEPLOY: -42}
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$WBTC_CONTRACT_ADDRESS" 0x6767114FFAA17C6439D7AEA480738B982CE63A02 100000000000000000
# seed some evm wallets # seed some evm wallets
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_WBTC_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 10000000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_WBTC_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 10000000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$MULTICHAIN_wBTC_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 10000000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$MULTICHAIN_wBTC_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 10000000000000
@ -91,6 +116,11 @@ npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$wETH_CONTRAC
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_USDC_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 100000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_USDC_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 100000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$MULTICHAIN_USDT_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 100000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$MULTICHAIN_USDT_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 100000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$TETHER_USDT_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 1000000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$TETHER_USDT_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 1000000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BNB_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 1000000000000000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BUSD_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 1000000000000000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_XRPB_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 1000000000000000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BTCB_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 1000000000000000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$WBTC_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 10000000000000
# seed webapp E2E whale account # seed webapp E2E whale account
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_WBTC_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 100000000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_WBTC_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 100000000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$MULTICHAIN_wBTC_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 10000000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$MULTICHAIN_wBTC_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 10000000000000
@ -99,6 +129,11 @@ npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$wETH_CONTRAC
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_USDC_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 10000000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_USDC_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 10000000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$MULTICHAIN_USDT_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 1000000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$MULTICHAIN_USDT_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 1000000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$TETHER_USDT_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 1000000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$TETHER_USDT_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 1000000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BNB_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 10000000000000000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BUSD_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 10000000000000000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BTCB_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 10000000000000000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_XRPB_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 10000000000000000000000
npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$WBTC_CONTRACT_ADDRESS" "$WBTC_CONTRACT_ADDRESS" 10000000000000
# give dev-wallet enough delegation power to pass proposals by itself # give dev-wallet enough delegation power to pass proposals by itself
@ -138,7 +173,7 @@ PARAM_CHANGE_PROP_TEMPLATE=$(
{ {
"subspace": "evmutil", "subspace": "evmutil",
"key": "EnabledConversionPairs", "key": "EnabledConversionPairs",
"value": "[{\"kava_erc20_address\":\"MULTICHAIN_USDC_CONTRACT_ADDRESS\",\"denom\":\"erc20/multichain/usdc\"},{\"kava_erc20_address\":\"MULTICHAIN_USDT_CONTRACT_ADDRESS\",\"denom\":\"erc20/multichain/usdt\"},{\"kava_erc20_address\":\"MULTICHAIN_wBTC_CONTRACT_ADDRESS\",\"denom\":\"erc20/multichain/wbtc\"},{\"kava_erc20_address\":\"AXL_USDC_CONTRACT_ADDRESS\",\"denom\":\"erc20/axelar/usdc\"},{\"kava_erc20_address\":\"AXL_WBTC_CONTRACT_ADDRESS\",\"denom\":\"erc20/axelar/wbtc\"},{\"kava_erc20_address\":\"wETH_CONTRACT_ADDRESS\",\"denom\":\"erc20/axelar/eth\"},{\"kava_erc20_address\":\"TETHER_USDT_CONTRACT_ADDRESS\",\"denom\":\"erc20/tether/usdt\"}]" "value": "[{\"kava_erc20_address\":\"MULTICHAIN_USDC_CONTRACT_ADDRESS\",\"denom\":\"erc20/multichain/usdc\"},{\"kava_erc20_address\":\"MULTICHAIN_USDT_CONTRACT_ADDRESS\",\"denom\":\"erc20/multichain/usdt\"},{\"kava_erc20_address\":\"MULTICHAIN_wBTC_CONTRACT_ADDRESS\",\"denom\":\"erc20/multichain/wbtc\"},{\"kava_erc20_address\":\"AXL_USDC_CONTRACT_ADDRESS\",\"denom\":\"erc20/axelar/usdc\"},{\"kava_erc20_address\":\"AXL_WBTC_CONTRACT_ADDRESS\",\"denom\":\"erc20/axelar/wbtc\"},{\"kava_erc20_address\":\"wETH_CONTRACT_ADDRESS\",\"denom\":\"erc20/axelar/eth\"},{\"kava_erc20_address\":\"TETHER_USDT_CONTRACT_ADDRESS\",\"denom\":\"erc20/tether/usdt\"},{\"kava_erc20_address\":\"AXL_BNB_CONTRACT_ADDRESS\",\"denom\":\"bnb\"},{\"kava_erc20_address\":\"AXL_BUSD_CONTRACT_ADDRESS\",\"denom\":\"busd\"},{\"kava_erc20_address\":\"AXL_BTCB_CONTRACT_ADDRESS\",\"denom\":\"btcb\"},{\"kava_erc20_address\":\"AXL_XRPB_CONTRACT_ADDRESS\",\"denom\":\"xrpb\"},{\"kava_erc20_address\":\"WBTC_CONTRACT_ADDRESS\",\"denom\":\"erc20/bitgo/wbtc\"}]"
} }
] ]
} }
@ -155,6 +190,11 @@ finalProposal="${finalProposal/AXL_USDC_CONTRACT_ADDRESS/$AXL_USDC_CONTRACT_ADDR
finalProposal="${finalProposal/AXL_WBTC_CONTRACT_ADDRESS/$AXL_WBTC_CONTRACT_ADDRESS}" finalProposal="${finalProposal/AXL_WBTC_CONTRACT_ADDRESS/$AXL_WBTC_CONTRACT_ADDRESS}"
finalProposal="${finalProposal/wETH_CONTRACT_ADDRESS/$wETH_CONTRACT_ADDRESS}" finalProposal="${finalProposal/wETH_CONTRACT_ADDRESS/$wETH_CONTRACT_ADDRESS}"
finalProposal="${finalProposal/TETHER_USDT_CONTRACT_ADDRESS/$TETHER_USDT_CONTRACT_ADDRESS}" finalProposal="${finalProposal/TETHER_USDT_CONTRACT_ADDRESS/$TETHER_USDT_CONTRACT_ADDRESS}"
finalProposal="${finalProposal/AXL_BNB_CONTRACT_ADDRESS/$AXL_BNB_CONTRACT_ADDRESS}"
finalProposal="${finalProposal/AXL_BUSD_CONTRACT_ADDRESS/$AXL_BUSD_CONTRACT_ADDRESS}"
finalProposal="${finalProposal/AXL_BTCB_CONTRACT_ADDRESS/$AXL_BTCB_CONTRACT_ADDRESS}"
finalProposal="${finalProposal/AXL_XRPB_CONTRACT_ADDRESS/$AXL_XRPB_CONTRACT_ADDRESS}"
finalProposal="${finalProposal/WBTC_CONTRACT_ADDRESS/$WBTC_CONTRACT_ADDRESS}"
# create unique proposal filename # create unique proposal filename
proposalFileName="$(date +%s)-proposal.json" proposalFileName="$(date +%s)-proposal.json"
@ -185,6 +225,21 @@ sleep $AVG_SECONDS_BETWEEN_BLOCKS
updatedEvmUtilParams=$(curl https://api.app.internal.testnet.us-east.production.kava.io/kava/evmutil/v1beta1/params) updatedEvmUtilParams=$(curl https://api.app.internal.testnet.us-east.production.kava.io/kava/evmutil/v1beta1/params)
printf "updated evm util module params\n %s" , "$updatedEvmUtilParams" printf "updated evm util module params\n %s" , "$updatedEvmUtilParams"
# submit a kava token committee proposal
COMMITTEE_PROP_TEMPLATE=$(
cat <<'END_HEREDOC'
{
"@type": "/cosmos.gov.v1beta1.TextProposal",
"title": "The next big thing signaling proposal.",
"description": "The purpose of this proposal is to signal support/opposition to the next big thing"
}
END_HEREDOC
)
committeeProposalFileName="$(date +%s)-committee-proposal.json"
echo "$COMMITTEE_PROP_TEMPLATE" >$committeeProposalFileName
tokenCommitteeId=4
kava tx committee submit-proposal "$tokenCommitteeId" "$committeeProposalFileName" --gas auto --gas-adjustment 1.5 --gas-prices 0.01ukava --from god -y
# if adding more cosmos coins -> er20s, ensure that the deployment order below remains the same. # if adding more cosmos coins -> er20s, ensure that the deployment order below remains the same.
# convert 1 HARD to an erc20. doing this ensures the contract is deployed. # convert 1 HARD to an erc20. doing this ensures the contract is deployed.
kava tx evmutil convert-cosmos-coin-to-erc20 \ kava tx evmutil convert-cosmos-coin-to-erc20 \

View File

@ -67,7 +67,6 @@ jobs:
--update-playbook-filename=$PLAYBOOK_NAME \ --update-playbook-filename=$PLAYBOOK_NAME \
--chain-id=$CHAIN_ID \ --chain-id=$CHAIN_ID \
--max-upgrade-batch-size=0 \ --max-upgrade-batch-size=0 \
--node-states=Standby \
--wait-for-node-sync-after-upgrade=false --wait-for-node-sync-after-upgrade=false
env: env:
SSM_DOCUMENT_NAME: ${{ inputs.ssm-document-name }} SSM_DOCUMENT_NAME: ${{ inputs.ssm-document-name }}

View File

@ -35,12 +35,16 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
ref: master ref: master
- name: checkout version of kava used by network - name: get desired version of network
id: kava-version
run: | run: |
git pull -p echo "KAVA_VERSION=$(cat ./ci/env/kava-internal-testnet/KAVA.VERSION)" >> $GITHUB_OUTPUT
git checkout $(cat ${KAVA_VERSION_FILEPATH})
env: env:
KAVA_VERSION_FILEPATH: ${{ inputs.kava_version_filepath }} KAVA_VERSION_FILEPATH: ${{ inputs.kava_version_filepath }}
- name: checkout version of kava used by network
uses: actions/checkout@v4
with:
ref: ${{ steps.kava-version.outputs.KAVA_VERSION }}
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v4 uses: actions/setup-go@v4
with: with:
@ -68,7 +72,7 @@ jobs:
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
cache: npm cache: npm
node-version: 18 node-version-file: .tool-versions
cache-dependency-path: kava-bridge/contract/package.json cache-dependency-path: kava-bridge/contract/package.json
- name: "install ERC20 contract deployment dependencies" - name: "install ERC20 contract deployment dependencies"
run: "npm install" run: "npm install"

View File

@ -63,7 +63,6 @@ jobs:
--update-playbook-filename=$PLAYBOOK_NAME \ --update-playbook-filename=$PLAYBOOK_NAME \
--chain-id=$CHAIN_ID \ --chain-id=$CHAIN_ID \
--max-upgrade-batch-size=0 \ --max-upgrade-batch-size=0 \
--node-states=Standby \
--wait-for-node-sync-after-upgrade=true --wait-for-node-sync-after-upgrade=true
env: env:
SSM_DOCUMENT_NAME: ${{ inputs.ssm-document-name }} SSM_DOCUMENT_NAME: ${{ inputs.ssm-document-name }}

View File

@ -35,6 +35,35 @@ jobs:
run: make test run: make test
- name: run e2e tests - name: run e2e tests
run: make docker-build test-e2e run: make docker-build test-e2e
fuzz:
runs-on: ubuntu-latest
steps:
- name: checkout repo from current commit
uses: actions/checkout@v4
with:
submodules: true
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version-file: go.mod
cache-dependency-path: |
go.sum
- name: run fuzz tests
run: make test-fuzz
ibc-test:
runs-on: ubuntu-latest
steps:
- name: checkout repo from current commit
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: tests/e2e-ibc/go.mod
cache-dependency-path: |
tests/e2e-ibc/go.sum
go.sum
- name: run ibc e2e tests
run: make test-ibc
validate-internal-testnet-genesis: validate-internal-testnet-genesis:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@ -44,16 +73,10 @@ jobs:
id: kava-version id: kava-version
run: | run: |
echo "KAVA_VERSION=$(cat ./ci/env/kava-internal-testnet/KAVA.VERSION)" >> $GITHUB_OUTPUT echo "KAVA_VERSION=$(cat ./ci/env/kava-internal-testnet/KAVA.VERSION)" >> $GITHUB_OUTPUT
- name: checkout repo from master - name: checkout version of kava that will be deployed if this pr is merged
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
ref: master ref: ${{ steps.kava-version.outputs.KAVA_VERSION }}
- name: checkout version of kava that will be deployed if this pr is merged
run: |
git pull -p
git checkout $KAVA_VERSION
env:
KAVA_VERSION: ${{ steps.kava-version.outputs.KAVA_VERSION }}
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v4 uses: actions/setup-go@v4
with: with:

View File

@ -50,6 +50,17 @@ jobs:
username: ${{ inputs.dockerhub-username }} username: ${{ inputs.dockerhub-username }}
password: ${{ secrets.CI_DOCKERHUB_TOKEN }} password: ${{ secrets.CI_DOCKERHUB_TOKEN }}
- name: Go Build Cache for Docker
uses: actions/cache@v3
with:
path: go-build-cache
key: ${{ runner.os }}-go-build-cache-${{ hashFiles('**/go.sum') }}
- name: inject go-build-cache into docker
uses: reproducible-containers/buildkit-cache-dance@v2.1.2
with:
cache-source: go-build-cache
# publish to docker hub, tag with short git hash # publish to docker hub, tag with short git hash
- name: Build and push (goleveldb) - name: Build and push (goleveldb)
uses: docker/build-push-action@v5 uses: docker/build-push-action@v5
@ -89,6 +100,17 @@ jobs:
username: ${{ inputs.dockerhub-username }} username: ${{ inputs.dockerhub-username }}
password: ${{ secrets.CI_DOCKERHUB_TOKEN }} password: ${{ secrets.CI_DOCKERHUB_TOKEN }}
- name: Go Build Cache for Docker
uses: actions/cache@v3
with:
path: go-build-cache
key: ${{ runner.os }}-go-build-cache-${{ hashFiles('**/go.sum') }}
- name: inject go-build-cache into docker
uses: reproducible-containers/buildkit-cache-dance@v2.1.2
with:
cache-source: go-build-cache
# publish to docker hub, tag with short git hash # publish to docker hub, tag with short git hash
- name: Build and push (rocksdb) - name: Build and push (rocksdb)
uses: docker/build-push-action@v5 uses: docker/build-push-action@v5

View File

@ -7,11 +7,25 @@ jobs:
uses: ./.github/workflows/proto.yml uses: ./.github/workflows/proto.yml
golangci-lint: golangci-lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
checks: write # allow write access to checks to allow the action to annotate code in the PR.
steps: steps:
- uses: actions/checkout@v4 - name: Checkout code
- name: golangci-lint uses: actions/checkout@v4
uses: reviewdog/action-golangci-lint@v2 with: { fetch-depth: 0 }
- name: Set up Go
uses: actions/setup-go@v4
with: with:
github_token: ${{ secrets.github_token }} go-version-file: go.mod
reporter: github-pr-review - name: Load Version
golangci_lint_flags: --timeout 10m id: load-version
run: |
GOLANGCI_VERSION=$(cat .golangci-version)
REV=$(git merge-base origin/master HEAD)
echo "GOLANGCI_VERSION=$GOLANGCI_VERSION" >> $GITHUB_ENV
echo "REV=$REV" >> $GITHUB_ENV
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: ${{ env.GOLANGCI_VERSION }}
args: -v -c .golangci.yml --new-from-rev ${{ env.REV }}

View File

@ -45,6 +45,9 @@ jobs:
dockerhub-username: kavaops dockerhub-username: kavaops
extra-image-tag: master extra-image-tag: master
secrets: inherit secrets: inherit
rosetta:
uses: ./.github/workflows/ci-rosetta.yml
secrets: inherit
post-pipeline-metrics: post-pipeline-metrics:
uses: ./.github/workflows/metric-pipeline.yml uses: ./.github/workflows/metric-pipeline.yml
if: always() # always run so we metric failures and successes if: always() # always run so we metric failures and successes

27
.github/workflows/ci-pr-lint.yml vendored Normal file
View File

@ -0,0 +1,27 @@
# this workflow is responsible for ensuring quality titles are given to all PRs
# for PR checks to pass, the title must follow the Conventional Commits standard
# https://www.conventionalcommits.org/en/v1.0.0/
# this workflow was adapted from a similar workflow in https://github.com/cosmos/cosmos-sdk
name: "Lint PR Title"
on:
pull_request_target:
types:
- opened
- edited
- synchronize
permissions:
contents: read
jobs:
main:
permissions:
pull-requests: read # for amannn/action-semantic-pull-request to analyze PRs
statuses: write # for amannn/action-semantic-pull-request to mark status of analyzed PR
runs-on: ubuntu-latest
steps:
# https://github.com/marketplace/actions/semantic-pull-request
- uses: amannn/action-semantic-pull-request@v5.5.3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -4,9 +4,6 @@ on:
tags: tags:
- "v[0-9]+.[0-9]+.[0-9]+*" - "v[0-9]+.[0-9]+.[0-9]+*"
jobs: jobs:
# run per commit ci checks against released version
lint-checks:
uses: ./.github/workflows/ci-lint.yml
# run default ci checks against released version # run default ci checks against released version
default-checks: default-checks:
uses: ./.github/workflows/ci-default.yml uses: ./.github/workflows/ci-default.yml
@ -14,7 +11,7 @@ jobs:
# get the version tag that triggered this workflow # get the version tag that triggered this workflow
get-version-tag: get-version-tag:
# prep version release only if all checks pass # prep version release only if all checks pass
needs: [lint-checks, default-checks] needs: default-checks
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs: outputs:
git-tag: ${{ steps.git-tag.outputs.tag }} git-tag: ${{ steps.git-tag.outputs.tag }}

View File

@ -19,25 +19,3 @@ jobs:
run: bash ${GITHUB_WORKSPACE}/.github/scripts/install-rocksdb.sh run: bash ${GITHUB_WORKSPACE}/.github/scripts/install-rocksdb.sh
- name: build application - name: build application
run: make build COSMOS_BUILD_OPTIONS=rocksdb run: make build COSMOS_BUILD_OPTIONS=rocksdb
test:
runs-on: ubuntu-latest
steps:
- name: install RocksDB dependencies
run: sudo apt-get update
&& sudo apt-get install -y git make gcc libgflags-dev libsnappy-dev zlib1g-dev libbz2-dev liblz4-dev libzstd-dev
- name: install RocksDB as shared library
run: git clone https://github.com/facebook/rocksdb.git
&& cd rocksdb
&& git checkout $ROCKSDB_VERSION
&& sudo make -j$(nproc) install-shared
&& sudo ldconfig
- name: checkout repo from current commit
uses: actions/checkout@v4
with:
submodules: true
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version-file: go.mod
- name: run unit tests
run: make test-rocksdb

16
.github/workflows/ci-rosetta.yml vendored Normal file
View File

@ -0,0 +1,16 @@
name: Dispatch run-rosetta-tests event to rosetta-kava
on:
workflow_call:
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Dispatch run-rosetta-tests event to rosetta-kava
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.KAVA_PUBLIC_GITHUB_ACCESS_TOKEN }}
repository: Kava-Labs/rosetta-kava
event-type: run-rosetta-tests
client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}"}'

3
.gitignore vendored
View File

@ -31,6 +31,9 @@ out
# Ignore build cache dir # Ignore build cache dir
build/.cache build/.cache
# Ignore make lint cache
build/.golangci-lint
# Ignore installed binaires # Ignore installed binaires
build/bin build/bin

1
.golangci-version Normal file
View File

@ -0,0 +1 @@
v1.59

130
.golangci.yml Normal file
View File

@ -0,0 +1,130 @@
run:
timeout: 20m # set maximum time allowed for the linter to run. If the linting process exceeds this duration, it will be terminated
modules-download-mode: readonly # Ensures that modules are not modified during the linting process
allow-parallel-runners: true # enables parallel execution of linters to speed up linting process
linters:
disable-all: true
enable:
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- contextcheck
- decorder
- dogsled
# - dupl
# - dupword
- durationcheck
- errcheck
- errchkjson
- errname
- errorlint
# - exhaustive
- exportloopref
- funlen
- gci
- ginkgolinter
- gocheckcompilerdirectives
# - gochecknoglobals
# - gochecknoinits
- goconst
- gocritic
- godox
- gofmt
# - gofumpt
- goheader
- goimports
- mnd
# - gomodguard
- goprintffuncname
- gosec
- gosimple
- govet
- grouper
- importas
- ineffassign
# - interfacebloat
- lll
- loggercheck
- makezero
- mirror
- misspell
- musttag
# - nakedret
# - nestif
- nilerr
# - nilnil
# - noctx
- nolintlint
# - nonamedreturns
- nosprintfhostport
- prealloc
- predeclared
- promlinter
# - reassign
- revive
- rowserrcheck
- staticcheck
# - stylecheck
- tagalign
# - testpackage
# - thelper
# - tparallel
- typecheck
# - unconvert
- unparam
- unused
# - usestdlibvars
- wastedassign
# - whitespace
- wrapcheck
issues:
exclude-rules:
# Disable funlen for "func Test..." or func (suite *Suite) Test..." type functions
# These functions tend to be descriptive and exceed length limits.
- source: "^func (\\(.*\\) )?Test"
linters:
- funlen
linters-settings:
errcheck:
check-blank: true # check for assignments to the blank identifier '_' when errors are returned
check-type-assertions: false # check type assertion
errorlint:
check-generated: false # disabled linting of generated files
default-signifies-exhaustive: false # exhaustive handling of error types
exhaustive:
default-signifies-exhaustive: false # exhaustive handling of error types
gci:
sections: # defines the order of import sections
- standard
- default
- localmodule
goconst:
min-len: 3 # min length for string constants to be checked
min-occurrences: 3 # min occurrences of the same constant before it's flagged
godox:
keywords: # specific keywords to flag for further action
- BUG
- FIXME
- HACK
gosec:
exclude-generated: true
lll:
line-length: 120
misspell:
locale: US
ignore-words: expect
nolintlint:
allow-leading-space: false
require-explanation: true
require-specific: true
prealloc:
simple: true # enables simple preallocation checks
range-loops: true # enabled preallocation checks in range loops
for-loops: false # disables preallocation checks in for loops
unparam:
check-exported: true # checks exported functions and methods for unused params

16
.mockery.yaml Normal file
View File

@ -0,0 +1,16 @@
# Generate EXPECT() methods, type-safe methods to generate call expectations
with-expecter: true
# Generate mocks in adjacent mocks directory to the interfaces
dir: "{{.InterfaceDir}}/mocks"
mockname: "Mock{{.InterfaceName}}"
outpkg: "mocks"
filename: "Mock{{.InterfaceName}}.go"
packages:
github.com/0glabs/0g-chain/x/precisebank/types:
# package-specific config
config:
interfaces:
AccountKeeper:
BankKeeper:

View File

@ -1,2 +1,2 @@
golang 1.21 golang 1.21.9
nodejs 18.16.0 nodejs 20.16.0

View File

@ -38,6 +38,16 @@ Ref: https://keepachangelog.com/en/1.0.0/
## [v0.26.0] ## [v0.26.0]
### Features
- (precisebank) [#1906] Add new `x/precisebank` module with bank decimal extension for EVM usage.
- (cli) [#1922] Add `iavlviewer` CLI command for low-level iavl db debugging.
### Improvements
- (rocksdb) [#1903] Bump cometbft-db dependency for use with rocksdb v8.10.0
- (deps) [#1988] Bump cometbft to v0.37.9-kava.1
## [v0.26.0]
### Features ### Features
- (cli) [#1785] Add `shard` CLI command to support creating partitions of data for standalone nodes - (cli) [#1785] Add `shard` CLI command to support creating partitions of data for standalone nodes
@ -330,6 +340,10 @@ the [changelog](https://github.com/cosmos/cosmos-sdk/blob/v0.38.4/CHANGELOG.md).
- [#257](https://github.com/Kava-Labs/kava/pulls/257) Include scripts to run - [#257](https://github.com/Kava-Labs/kava/pulls/257) Include scripts to run
large-scale simulations remotely using aws-batch large-scale simulations remotely using aws-batch
[#1988]: https://github.com/Kava-Labs/kava/pull/1988
[#1922]: https://github.com/Kava-Labs/kava/pull/1922
[#1906]: https://github.com/Kava-Labs/kava/pull/1906
[#1903]: https://github.com/Kava-Labs/kava/pull/1903
[#1846]: https://github.com/Kava-Labs/kava/pull/1846 [#1846]: https://github.com/Kava-Labs/kava/pull/1846
[#1848]: https://github.com/Kava-Labs/kava/pull/1848 [#1848]: https://github.com/Kava-Labs/kava/pull/1848
[#1839]: https://github.com/Kava-Labs/kava/pull/1839 [#1839]: https://github.com/Kava-Labs/kava/pull/1839
@ -392,8 +406,9 @@ the [changelog](https://github.com/cosmos/cosmos-sdk/blob/v0.38.4/CHANGELOG.md).
[#750]: https://github.com/Kava-Labs/kava/pull/750 [#750]: https://github.com/Kava-Labs/kava/pull/750
[#751]: https://github.com/Kava-Labs/kava/pull/751 [#751]: https://github.com/Kava-Labs/kava/pull/751
[#780]: https://github.com/Kava-Labs/kava/pull/780 [#780]: https://github.com/Kava-Labs/kava/pull/780
[unreleased]: https://github.com/Kava-Labs/kava/compare/v0.25.0...HEAD [unreleased]: https://github.com/Kava-Labs/kava/compare/v0.26.0...HEAD
[v0.25.0]: https://github.com/Kava-Labs/kava/compare/v0.25.0...v0.24.3 [v0.26.0]: https://github.com/Kava-Labs/kava/compare/v0.25.0...v0.26.0
[v0.25.0]: https://github.com/Kava-Labs/kava/compare/v0.24.3...v0.25.0
[v0.24.3]: https://github.com/Kava-Labs/kava/compare/v0.24.3...v0.24.1 [v0.24.3]: https://github.com/Kava-Labs/kava/compare/v0.24.3...v0.24.1
[v0.24.1]: https://github.com/Kava-Labs/kava/compare/v0.24.1...v0.24.0 [v0.24.1]: https://github.com/Kava-Labs/kava/compare/v0.24.1...v0.24.0
[v0.24.0]: https://github.com/Kava-Labs/kava/compare/v0.24.0...v0.23.2 [v0.24.0]: https://github.com/Kava-Labs/kava/compare/v0.24.0...v0.23.2

View File

@ -1,23 +1,6 @@
FROM golang:1.20-bullseye AS chain-builder FROM kava/rocksdb:v8.10.1-go1.21 AS kava-builder
# Set up dependencies RUN apt-get update
RUN apt-get update \
&& apt-get install -y git make gcc libgflags-dev libsnappy-dev zlib1g-dev libbz2-dev liblz4-dev libzstd-dev \
&& rm -rf /var/lib/apt/lists/*
# Set working directory for the build
WORKDIR /root
# default home directory is /root
# install rocksdb
ARG rocksdb_version=v8.10.0
ENV ROCKSDB_VERSION=$rocksdb_version
RUN git clone https://github.com/facebook/rocksdb.git \
&& cd rocksdb \
&& git checkout $ROCKSDB_VERSION \
&& make -j$(nproc) install-shared \
&& ldconfig
WORKDIR /root/0gchain WORKDIR /root/0gchain
# Copy dependency files first to facilitate dependency caching # Copy dependency files first to facilitate dependency caching

22
Dockerfile-rocksdb-base Normal file
View File

@ -0,0 +1,22 @@
# published to https://hub.docker.com/repository/docker/kava/rocksdb/tags
# docker buildx build --platform linux/amd64,linux/arm64 -t kava/rocksdb:v8.10.1-go1.21 -f Dockerfile-rocksdb-base . --push
FROM golang:1.21-bullseye
# Set up dependencies
RUN apt-get update \
&& apt-get install -y git make gcc libgflags-dev libsnappy-dev zlib1g-dev libbz2-dev liblz4-dev libzstd-dev \
&& rm -rf /var/lib/apt/lists/*
# Set working directory for the build
WORKDIR /root
# default home directory is /root
# install rocksdb
ARG rocksdb_version=v8.10.0
ENV ROCKSDB_VERSION=$rocksdb_version
RUN git clone https://github.com/facebook/rocksdb.git \
&& cd rocksdb \
&& git checkout $ROCKSDB_VERSION \
&& make -j$(nproc) install-shared \
&& ldconfig

View File

@ -105,6 +105,8 @@ include $(BUILD_DIR)/deps.mk
include $(BUILD_DIR)/proto.mk include $(BUILD_DIR)/proto.mk
include $(BUILD_DIR)/proto-deps.mk include $(BUILD_DIR)/proto-deps.mk
include $(BUILD_DIR)/lint.mk
#export GO111MODULE = on #export GO111MODULE = on
# process build tags # process build tags
build_tags = netgo build_tags = netgo
@ -208,6 +210,14 @@ build-release: go.sum
build-linux: go.sum build-linux: go.sum
LEDGER_ENABLED=false GOOS=linux GOARCH=amd64 $(MAKE) build LEDGER_ENABLED=false GOOS=linux GOARCH=amd64 $(MAKE) build
# build on rocksdb-backed kava on macOS with shared libs from brew
# this assumes you are on macOS & these deps have been installed with brew:
# rocksdb, snappy, lz4, and zstd
# use like `make build-rocksdb-brew COSMOS_BUILD_OPTIONS=rocksdb`
build-rocksdb-brew:
export CGO_CFLAGS := -I$(shell brew --prefix rocksdb)/include
export CGO_LDFLAGS := -L$(shell brew --prefix rocksdb)/lib -lrocksdb -lstdc++ -lm -lz -L$(shell brew --prefix snappy)/lib -L$(shell brew --prefix lz4)/lib -L$(shell brew --prefix zstd)/lib
install: go.sum install: go.sum
$(GO_BIN) install -mod=readonly $(BUILD_FLAGS) $(MAIN_ENTRY) $(GO_BIN) install -mod=readonly $(BUILD_FLAGS) $(MAIN_ENTRY)
@ -234,13 +244,6 @@ link-check:
# TODO: replace kava in following line with project name # TODO: replace kava in following line with project name
liche -r . --exclude "^http://127.*|^https://riot.im/app*|^http://kava-testnet*|^https://testnet-dex*|^https://kava3.data.kava.io*|^https://ipfs.io*|^https://apps.apple.com*|^https://kava.quicksync.io*" liche -r . --exclude "^http://127.*|^https://riot.im/app*|^http://kava-testnet*|^https://testnet-dex*|^https://kava3.data.kava.io*|^https://ipfs.io*|^https://apps.apple.com*|^https://kava.quicksync.io*"
lint:
golangci-lint run
find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" | xargs gofmt -d -s
$(GO_BIN) mod verify
.PHONY: lint
format: format:
find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -name '*.pb.go' | xargs gofmt -w -s find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -name '*.pb.go' | xargs gofmt -w -s
find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -name '*.pb.go' | xargs misspell -w find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -name '*.pb.go' | xargs misspell -w
@ -265,11 +268,11 @@ build-docker-local-0gchain:
# Run a 4-node testnet locally # Run a 4-node testnet locally
localnet-start: build-linux localnet-stop localnet-start: build-linux localnet-stop
@if ! [ -f build/node0/kvd/config/genesis.json ]; then docker run --rm -v $(CURDIR)/build:/kvd:Z $(DOCKER_IMAGE_NAME)-node testnet --v 4 -o . --starting-ip-address 192.168.10.2 --keyring-backend=test ; fi @if ! [ -f build/node0/kvd/config/genesis.json ]; then docker run --rm -v $(CURDIR)/build:/kvd:Z kava/kavanode testnet --v 4 -o . --starting-ip-address 192.168.10.2 --keyring-backend=test ; fi
docker-compose up -d $(DOCKER) compose up -d
localnet-stop: localnet-stop:
docker-compose down $(DOCKER) compose down
# Launch a new single validator chain # Launch a new single validator chain
start: start:
@ -311,12 +314,14 @@ test-basic: test
test-e2e: docker-build test-e2e: docker-build
$(GO_BIN) test -failfast -count=1 -v ./tests/e2e/... $(GO_BIN) test -failfast -count=1 -v ./tests/e2e/...
# run interchaintest tests (./tests/e2e-ibc)
test-ibc: docker-build
cd tests/e2e-ibc && KAVA_TAG=local $(GO_BIN) test -timeout 10m .
.PHONY: test-ibc
test: test:
@$(GO_BIN) test $$($(GO_BIN) list ./... | grep -v 'contrib' | grep -v 'tests/e2e') @$(GO_BIN) test $$($(GO_BIN) list ./... | grep -v 'contrib' | grep -v 'tests/e2e')
test-rocksdb:
@go test -tags=rocksdb $(MAIN_ENTRY)/opendb
# Run cli integration tests # Run cli integration tests
# `-p 4` to use 4 cores, `-tags cli_test` to tell $(GO_BIN) not to ignore the cli package # `-p 4` to use 4 cores, `-tags cli_test` to tell $(GO_BIN) not to ignore the cli package
# These tests use the `kvd` or `kvcli` binaries in the build dir, or in `$BUILDDIR` if that env var is set. # These tests use the `kvd` or `kvcli` binaries in the build dir, or in `$BUILDDIR` if that env var is set.
@ -327,6 +332,18 @@ test-cli: build
test-migrate: test-migrate:
@$(GO_BIN) test -v -count=1 ./migrate/... @$(GO_BIN) test -v -count=1 ./migrate/...
# Use the old Apple linker to workaround broken xcode - https://github.com/golang/go/issues/65169
ifeq ($(OS_FAMILY),Darwin)
FUZZLDFLAGS := -ldflags=-extldflags=-Wl,-ld_classic
endif
test-fuzz:
@$(GO_BIN) test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzMintCoins ./x/precisebank/keeper
@$(GO_BIN) test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzBurnCoins ./x/precisebank/keeper
@$(GO_BIN) test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzSendCoins ./x/precisebank/keeper
@$(GO_BIN) test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzGenesisStateValidate_NonZeroRemainder ./x/precisebank/types
@$(GO_BIN) test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzGenesisStateValidate_ZeroRemainder ./x/precisebank/types
# Kick start lots of sims on an AWS cluster. # Kick start lots of sims on an AWS cluster.
# This submits an AWS Batch job to run a lot of sims, each within a docker image. Results are uploaded to S3 # This submits an AWS Batch job to run a lot of sims, each within a docker image. Results are uploaded to S3
start-remote-sims: start-remote-sims:
@ -337,14 +354,14 @@ start-remote-sims:
# submit an array job on AWS Batch, using 1000 seeds, spot instances # submit an array job on AWS Batch, using 1000 seeds, spot instances
aws batch submit-job \ aws batch submit-job \
-—job-name "master-$(VERSION)" \ -—job-name "master-$(VERSION)" \
-—job-queue “simulation-1-queue-spot" \ -—job-queue "simulation-1-queue-spot" \
-—array-properties size=1000 \ -—array-properties size=1000 \
-—job-definition $(BINARY_NAME)-sim-master \ -—job-definition $(BINARY_NAME)-sim-master \
-—container-override environment=[{SIM_NAME=master-$(VERSION)}] -—container-override environment=[{SIM_NAME=master-$(VERSION)}]
update-kvtool: update-kvtool:
git submodule init || true git submodule init || true
git submodule update git submodule update --remote
cd tests/e2e/kvtool && make install cd tests/e2e/kvtool && make install
.PHONY: all build-linux install clean build test test-cli test-all test-rest test-basic start-remote-sims .PHONY: all build-linux install build test test-cli test-all test-rest test-basic test-fuzz start-remote-sims

View File

@ -17,13 +17,13 @@ Reference implementation of 0G Chain, the first modular AI chain. Built using th
<!--- <!---
## Mainnet ## Mainnet
The current recommended version of the software for mainnet is [v0.25.0](https://github.com/Kava-Labs/kava/releases/tag/v0.25.0) The master branch of this repository often contains considerable development work since the last mainnet release and is __not__ runnable on mainnet. The current recommended version of the software for mainnet is [v0.26.2](https://github.com/Kava-Labs/kava/releases/tag/v0.26.2) The `master` branch of this repository often contains considerable development work since the last mainnet release and is __not__ runnable on mainnet.
### Installation and Setup ### Installation and Setup
For detailed instructions see [the Kava docs](https://docs.kava.io/docs/participate/validator-node). For detailed instructions see [the Kava docs](https://docs.kava.io/docs/nodes-and-validators/validator-node).
```bash ```bash
git checkout v0.25.0 git checkout v0.26.2
make install make install
``` ```
@ -49,7 +49,7 @@ If you have technical questions or concerns, ask a developer or community member
## Security ## Security
If you find a security issue, please report it to security [at] kava.io. Depending on the verification and severity, a bug bounty may be available. If you find a security issue, please report it to security [at] kavalabs.io. Depending on the verification and severity, a bug bounty may be available.
## License ## License

View File

@ -405,7 +405,7 @@ func (suite *EIP712TestSuite) TestEIP712Tx() {
// usdxToMintAmt: 99, // usdxToMintAmt: 99,
// }, // },
{ {
name: "fails when convertion more erc20 usdc than balance", name: "fails when conversion more erc20 usdc than balance",
usdcDepositAmt: 51_000, usdcDepositAmt: 51_000,
usdxToMintAmt: 100, usdxToMintAmt: 100,
errMsg: "transfer amount exceeds balance", errMsg: "transfer amount exceeds balance",

View File

@ -95,6 +95,7 @@ import (
ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper" ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper"
solomachine "github.com/cosmos/ibc-go/v7/modules/light-clients/06-solomachine" solomachine "github.com/cosmos/ibc-go/v7/modules/light-clients/06-solomachine"
ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint"
"github.com/ethereum/go-ethereum/core/vm"
evmante "github.com/evmos/ethermint/app/ante" evmante "github.com/evmos/ethermint/app/ante"
ethermintconfig "github.com/evmos/ethermint/server/config" ethermintconfig "github.com/evmos/ethermint/server/config"
"github.com/evmos/ethermint/x/evm" "github.com/evmos/ethermint/x/evm"
@ -129,6 +130,9 @@ import (
issuance "github.com/0glabs/0g-chain/x/issuance" issuance "github.com/0glabs/0g-chain/x/issuance"
issuancekeeper "github.com/0glabs/0g-chain/x/issuance/keeper" issuancekeeper "github.com/0glabs/0g-chain/x/issuance/keeper"
issuancetypes "github.com/0glabs/0g-chain/x/issuance/types" issuancetypes "github.com/0glabs/0g-chain/x/issuance/types"
"github.com/0glabs/0g-chain/x/precisebank"
precisebankkeeper "github.com/0glabs/0g-chain/x/precisebank/keeper"
precisebanktypes "github.com/0glabs/0g-chain/x/precisebank/types"
pricefeed "github.com/0glabs/0g-chain/x/pricefeed" pricefeed "github.com/0glabs/0g-chain/x/pricefeed"
pricefeedkeeper "github.com/0glabs/0g-chain/x/pricefeed/keeper" pricefeedkeeper "github.com/0glabs/0g-chain/x/pricefeed/keeper"
pricefeedtypes "github.com/0glabs/0g-chain/x/pricefeed/types" pricefeedtypes "github.com/0glabs/0g-chain/x/pricefeed/types"
@ -136,7 +140,6 @@ import (
validatorvestingrest "github.com/0glabs/0g-chain/x/validator-vesting/client/rest" validatorvestingrest "github.com/0glabs/0g-chain/x/validator-vesting/client/rest"
validatorvestingtypes "github.com/0glabs/0g-chain/x/validator-vesting/types" validatorvestingtypes "github.com/0glabs/0g-chain/x/validator-vesting/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
) )
var ( var (
@ -178,6 +181,7 @@ var (
validatorvesting.AppModuleBasic{}, validatorvesting.AppModuleBasic{},
evmutil.AppModuleBasic{}, evmutil.AppModuleBasic{},
mint.AppModuleBasic{}, mint.AppModuleBasic{},
precisebank.AppModuleBasic{},
council.AppModuleBasic{}, council.AppModuleBasic{},
dasigners.AppModuleBasic{}, dasigners.AppModuleBasic{},
consensus.AppModuleBasic{}, consensus.AppModuleBasic{},
@ -199,6 +203,7 @@ var (
issuancetypes.ModuleAccountName: {authtypes.Minter, authtypes.Burner}, issuancetypes.ModuleAccountName: {authtypes.Minter, authtypes.Burner},
bep3types.ModuleName: {authtypes.Burner, authtypes.Minter}, bep3types.ModuleName: {authtypes.Burner, authtypes.Minter},
minttypes.ModuleName: {authtypes.Minter}, minttypes.ModuleName: {authtypes.Minter},
precisebanktypes.ModuleName: {authtypes.Minter, authtypes.Burner}, // used for reserve account to back fractional amounts
} }
) )
@ -268,6 +273,7 @@ type App struct {
mintKeeper mintkeeper.Keeper mintKeeper mintkeeper.Keeper
dasignersKeeper dasignerskeeper.Keeper dasignersKeeper dasignerskeeper.Keeper
consensusParamsKeeper consensusparamkeeper.Keeper consensusParamsKeeper consensusparamkeeper.Keeper
precisebankKeeper precisebankkeeper.Keeper
// make scoped keepers public for test purposes // make scoped keepers public for test purposes
ScopedIBCKeeper capabilitykeeper.ScopedKeeper ScopedIBCKeeper capabilitykeeper.ScopedKeeper
@ -318,7 +324,7 @@ func NewApp(
counciltypes.StoreKey, counciltypes.StoreKey,
dasignerstypes.StoreKey, dasignerstypes.StoreKey,
vestingtypes.StoreKey, vestingtypes.StoreKey,
consensusparamtypes.StoreKey, crisistypes.StoreKey, consensusparamtypes.StoreKey, crisistypes.StoreKey, precisebanktypes.StoreKey,
ibcwasmtypes.StoreKey, ibcwasmtypes.StoreKey,
) )
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey)
@ -482,7 +488,13 @@ func NewApp(
app.accountKeeper, app.accountKeeper,
) )
evmBankKeeper := evmutilkeeper.NewEvmBankKeeper(app.evmutilKeeper, app.bankKeeper, app.accountKeeper) app.precisebankKeeper = precisebankkeeper.NewKeeper(
app.appCodec,
keys[precisebanktypes.StoreKey],
app.bankKeeper,
app.accountKeeper,
)
// dasigners keeper // dasigners keeper
app.dasignersKeeper = dasignerskeeper.NewKeeper(keys[dasignerstypes.StoreKey], appCodec, app.stakingKeeper, govAuthAddrStr) app.dasignersKeeper = dasignerskeeper.NewKeeper(keys[dasignerstypes.StoreKey], appCodec, app.stakingKeeper, govAuthAddrStr)
// precopmiles // precopmiles
@ -492,16 +504,18 @@ func NewApp(
panic("initialize precompile failed") panic("initialize precompile failed")
} }
precompiles[daSignersPrecompile.Address()] = daSignersPrecompile precompiles[daSignersPrecompile.Address()] = daSignersPrecompile
// evm keeper
app.evmKeeper = evmkeeper.NewKeeper( app.evmKeeper = evmkeeper.NewKeeper(
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey],
govAuthAddr, govAuthAddr,
app.accountKeeper, evmBankKeeper, app.stakingKeeper, app.feeMarketKeeper, app.accountKeeper,
app.precisebankKeeper, // x/precisebank in place of x/bank
app.stakingKeeper,
app.feeMarketKeeper,
options.EVMTrace, options.EVMTrace,
evmSubspace, evmSubspace,
precompiles, precompiles,
) )
app.evmutilKeeper.SetEvmKeeper(app.evmKeeper) app.evmutilKeeper.SetEvmKeeper(app.evmKeeper)
// It's important to note that the PFM Keeper must be initialized before the Transfer Keeper // It's important to note that the PFM Keeper must be initialized before the Transfer Keeper
@ -669,6 +683,7 @@ func NewApp(
evmutil.NewAppModule(app.evmutilKeeper, app.bankKeeper, app.accountKeeper), evmutil.NewAppModule(app.evmutilKeeper, app.bankKeeper, app.accountKeeper),
// nil InflationCalculationFn, use SDK's default inflation function // nil InflationCalculationFn, use SDK's default inflation function
mint.NewAppModule(appCodec, app.mintKeeper, app.accountKeeper, nil, mintSubspace), mint.NewAppModule(appCodec, app.mintKeeper, app.accountKeeper, nil, mintSubspace),
precisebank.NewAppModule(app.precisebankKeeper, app.bankKeeper, app.accountKeeper),
council.NewAppModule(app.CouncilKeeper), council.NewAppModule(app.CouncilKeeper),
ibcwasm.NewAppModule(app.ibcWasmClientKeeper), ibcwasm.NewAppModule(app.ibcWasmClientKeeper),
dasigners.NewAppModule(app.dasignersKeeper, *app.stakingKeeper), dasigners.NewAppModule(app.dasignersKeeper, *app.stakingKeeper),
@ -716,6 +731,7 @@ func NewApp(
counciltypes.ModuleName, counciltypes.ModuleName,
consensusparamtypes.ModuleName, consensusparamtypes.ModuleName,
packetforwardtypes.ModuleName, packetforwardtypes.ModuleName,
precisebanktypes.ModuleName,
ibcwasmtypes.ModuleName, ibcwasmtypes.ModuleName,
dasignerstypes.ModuleName, dasignerstypes.ModuleName,
) )
@ -752,6 +768,7 @@ func NewApp(
counciltypes.ModuleName, counciltypes.ModuleName,
consensusparamtypes.ModuleName, consensusparamtypes.ModuleName,
packetforwardtypes.ModuleName, packetforwardtypes.ModuleName,
precisebanktypes.ModuleName,
ibcwasmtypes.ModuleName, ibcwasmtypes.ModuleName,
dasignerstypes.ModuleName, dasignerstypes.ModuleName,
) )
@ -786,6 +803,7 @@ func NewApp(
counciltypes.ModuleName, counciltypes.ModuleName,
consensusparamtypes.ModuleName, consensusparamtypes.ModuleName,
packetforwardtypes.ModuleName, packetforwardtypes.ModuleName,
precisebanktypes.ModuleName, // Must be run after x/bank to verify reserve balance
crisistypes.ModuleName, // runs the invariants at genesis, should run after other modules crisistypes.ModuleName, // runs the invariants at genesis, should run after other modules
ibcwasmtypes.ModuleName, ibcwasmtypes.ModuleName,
dasignerstypes.ModuleName, dasignerstypes.ModuleName,

View File

@ -3,9 +3,9 @@ Package params defines the simulation parameters for the 0gChain app.
It contains the default weights used for each transaction used on the module's It contains the default weights used for each transaction used on the module's
simulation. These weights define the chance for a transaction to be simulated at simulation. These weights define the chance for a transaction to be simulated at
any gived operation. any given operation.
You can repace the default values for the weights by providing a params.json You can replace the default values for the weights by providing a params.json
file with the weights defined for each of the transaction operations: file with the weights defined for each of the transaction operations:
{ {

View File

@ -130,7 +130,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() {
passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal) passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal)
suite.Falsef(passes, "expected proposal to fail, tally: %v", tally) suite.Falsef(passes, "expected proposal to fail, tally: %v", tally)
suite.Truef(burns, "expected desposit to be burned, tally: %v", tally) suite.Truef(burns, "expected deposit to be burned, tally: %v", tally)
}) })
suite.Run("VetoedFails", func() { suite.Run("VetoedFails", func() {
suite.SetupTest() suite.SetupTest()
@ -145,7 +145,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() {
passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal) passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal)
suite.Falsef(passes, "expected proposal to fail, tally: %v", tally) suite.Falsef(passes, "expected proposal to fail, tally: %v", tally)
suite.Truef(burns, "expected desposit to be burned, tally: %v", tally) suite.Truef(burns, "expected deposit to be burned, tally: %v", tally)
}) })
suite.Run("UnvetoedAndYesAboveThresholdPasses", func() { suite.Run("UnvetoedAndYesAboveThresholdPasses", func() {
suite.SetupTest() suite.SetupTest()
@ -162,7 +162,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() {
passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal) passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal)
suite.Truef(passes, "expected proposal to pass, tally: %v", tally) suite.Truef(passes, "expected proposal to pass, tally: %v", tally)
suite.Falsef(burns, "expected desposit to not burn, tally: %v", tally) suite.Falsef(burns, "expected deposit to not burn, tally: %v", tally)
}) })
suite.Run("UnvetoedAndYesBelowThresholdFails", func() { suite.Run("UnvetoedAndYesBelowThresholdFails", func() {
suite.SetupTest() suite.SetupTest()
@ -179,7 +179,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() {
passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal) passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal)
suite.Falsef(passes, "expected proposal to pass, tally: %v", tally) suite.Falsef(passes, "expected proposal to pass, tally: %v", tally)
suite.Falsef(burns, "expected desposit to not burn, tally: %v", tally) suite.Falsef(burns, "expected deposit to not burn, tally: %v", tally)
}) })
suite.Run("NotEnoughStakeFails", func() { suite.Run("NotEnoughStakeFails", func() {
suite.SetupTest() suite.SetupTest()
@ -191,7 +191,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() {
passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal) passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal)
suite.Falsef(passes, "expected proposal to pass, tally: %v", tally) suite.Falsef(passes, "expected proposal to pass, tally: %v", tally)
suite.Falsef(burns, "expected desposit to not burn, tally: %v", tally) suite.Falsef(burns, "expected deposit to not burn, tally: %v", tally)
}) })
suite.Run("UnvetoedAndAllAbstainedFails", func() { suite.Run("UnvetoedAndAllAbstainedFails", func() {
suite.SetupTest() suite.SetupTest()
@ -204,7 +204,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() {
passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal) passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal)
suite.Falsef(passes, "expected proposal to pass, tally: %v", tally) suite.Falsef(passes, "expected proposal to pass, tally: %v", tally)
suite.Falsef(burns, "expected desposit to not burn, tally: %v", tally) suite.Falsef(burns, "expected deposit to not burn, tally: %v", tally)
}) })
} }

View File

@ -47,6 +47,7 @@ import (
committeekeeper "github.com/0glabs/0g-chain/x/committee/keeper" committeekeeper "github.com/0glabs/0g-chain/x/committee/keeper"
evmutilkeeper "github.com/0glabs/0g-chain/x/evmutil/keeper" evmutilkeeper "github.com/0glabs/0g-chain/x/evmutil/keeper"
issuancekeeper "github.com/0glabs/0g-chain/x/issuance/keeper" issuancekeeper "github.com/0glabs/0g-chain/x/issuance/keeper"
precisebankkeeper "github.com/0glabs/0g-chain/x/precisebank/keeper"
pricefeedkeeper "github.com/0glabs/0g-chain/x/pricefeed/keeper" pricefeedkeeper "github.com/0glabs/0g-chain/x/pricefeed/keeper"
) )
@ -116,11 +117,16 @@ func (tApp TestApp) GetEvmutilKeeper() evmutilkeeper.Keeper { return tApp.ev
func (tApp TestApp) GetEvmKeeper() *evmkeeper.Keeper { return tApp.evmKeeper } func (tApp TestApp) GetEvmKeeper() *evmkeeper.Keeper { return tApp.evmKeeper }
func (tApp TestApp) GetFeeMarketKeeper() feemarketkeeper.Keeper { return tApp.feeMarketKeeper } func (tApp TestApp) GetFeeMarketKeeper() feemarketkeeper.Keeper { return tApp.feeMarketKeeper }
func (tApp TestApp) GetDASignersKeeper() dasignerskeeper.Keeper { return tApp.dasignersKeeper } func (tApp TestApp) GetDASignersKeeper() dasignerskeeper.Keeper { return tApp.dasignersKeeper }
func (tApp TestApp) GetPrecisebankKeeper() precisebankkeeper.Keeper { return tApp.precisebankKeeper }
func (tApp TestApp) GetKVStoreKey(key string) *storetypes.KVStoreKey { func (tApp TestApp) GetKVStoreKey(key string) *storetypes.KVStoreKey {
return tApp.keys[key] return tApp.keys[key]
} }
func (tApp TestApp) GetBlockedMaccAddrs() map[string]bool {
return tApp.loadBlockedMaccAddrs()
}
// LegacyAmino returns the app's amino codec. // LegacyAmino returns the app's amino codec.
func (app *App) LegacyAmino() *codec.LegacyAmino { func (app *App) LegacyAmino() *codec.LegacyAmino {
return app.legacyAmino return app.legacyAmino
@ -465,7 +471,7 @@ func (tApp TestApp) SetInflation(ctx sdk.Context, value sdk.Dec) {
mk.SetParams(ctx, mintParams) mk.SetParams(ctx, mintParams)
} }
// GeneratePrivKeyAddressPairsFromRand generates (deterministically) a total of n private keys and addresses. // GeneratePrivKeyAddressPairs generates (deterministically) a total of n private keys and addresses.
func GeneratePrivKeyAddressPairs(n int) (keys []cryptotypes.PrivKey, addrs []sdk.AccAddress) { func GeneratePrivKeyAddressPairs(n int) (keys []cryptotypes.PrivKey, addrs []sdk.AccAddress) {
r := rand.New(rand.NewSource(12345)) // make the generation deterministic r := rand.New(rand.NewSource(12345)) // make the generation deterministic
keys = make([]cryptotypes.PrivKey, n) keys = make([]cryptotypes.PrivKey, n)

View File

@ -3,13 +3,21 @@ package app
import ( import (
"fmt" "fmt"
sdkmath "cosmossdk.io/math"
evmutilkeeper "github.com/0glabs/0g-chain/x/evmutil/keeper"
evmutiltypes "github.com/0glabs/0g-chain/x/evmutil/types"
precisebankkeeper "github.com/0glabs/0g-chain/x/precisebank/keeper"
precisebanktypes "github.com/0glabs/0g-chain/x/precisebank/types"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/types/module"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
) )
const ( const (
UpgradeName_Testnet = "v0.3.1" UpgradeName_Testnet = "v0.4.0"
) )
// RegisterUpgradeHandlers registers the upgrade handlers for the app. // RegisterUpgradeHandlers registers the upgrade handlers for the app.
@ -18,6 +26,24 @@ func (app App) RegisterUpgradeHandlers() {
UpgradeName_Testnet, UpgradeName_Testnet,
upgradeHandler(app, UpgradeName_Testnet), upgradeHandler(app, UpgradeName_Testnet),
) )
upgradeInfo, err := app.upgradeKeeper.ReadUpgradeInfoFromDisk()
if err != nil {
panic(err)
}
doUpgrade := upgradeInfo.Name == UpgradeName_Testnet
if doUpgrade && !app.upgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
storeUpgrades := storetypes.StoreUpgrades{
Added: []string{
precisebanktypes.ModuleName,
},
}
// configure store loader that checks if version == upgradeHeight and applies store upgrades
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades))
}
} }
// upgradeHandler returns an UpgradeHandler for the given upgrade parameters. // upgradeHandler returns an UpgradeHandler for the given upgrade parameters.
@ -30,13 +56,213 @@ func upgradeHandler(
plan upgradetypes.Plan, plan upgradetypes.Plan,
fromVM module.VersionMap, fromVM module.VersionMap,
) (module.VersionMap, error) { ) (module.VersionMap, error) {
app.Logger().Info(fmt.Sprintf("running %s upgrade handler", name)) logger := app.Logger()
logger.Info(fmt.Sprintf("running %s upgrade handler", name))
params := app.mintKeeper.GetParams(ctx) // Run migrations for all modules and return new consensus version map.
params.MintDenom = "ua0gi" versionMap, err := app.mm.RunMigrations(ctx, app.configurator, fromVM)
app.mintKeeper.SetParams(ctx, params) if err != nil {
return nil, err
}
// run migrations for all modules and return new consensus version map logger.Info("completed store migrations")
return app.mm.RunMigrations(ctx, app.configurator, fromVM)
// Migration of fractional balances from x/evmutil to x/precisebank
if err := MigrateEvmutilToPrecisebank(
ctx,
app.accountKeeper,
app.bankKeeper,
app.evmutilKeeper,
app.precisebankKeeper,
); err != nil {
return nil, err
}
logger.Info("completed x/evmutil to x/precisebank migration")
return versionMap, nil
} }
} }
// MigrateEvmutilToPrecisebank migrates all required state from x/evmutil to
// x/precisebank and ensures the resulting state is correct.
// This migrates the following state:
// - Fractional balances
// - Fractional balance reserve
// Initializes the following state in x/precisebank:
// - Remainder amount
func MigrateEvmutilToPrecisebank(
ctx sdk.Context,
accountKeeper evmutiltypes.AccountKeeper,
bankKeeper bankkeeper.Keeper,
evmutilKeeper evmutilkeeper.Keeper,
precisebankKeeper precisebankkeeper.Keeper,
) error {
logger := ctx.Logger()
aggregateSum, err := TransferFractionalBalances(
ctx,
evmutilKeeper,
precisebankKeeper,
)
if err != nil {
return fmt.Errorf("fractional balances transfer: %w", err)
}
logger.Info(
"fractional balances transferred from x/evmutil to x/precisebank",
"aggregate sum", aggregateSum,
)
remainder := InitializeRemainder(ctx, precisebankKeeper, aggregateSum)
logger.Info("remainder amount initialized in x/precisebank", "remainder", remainder)
// Migrate fractional balances, reserve, and ensure reserve fully backs all
// fractional balances.
if err := TransferFractionalBalanceReserve(
ctx,
accountKeeper,
bankKeeper,
precisebankKeeper,
); err != nil {
return fmt.Errorf("reserve transfer: %w", err)
}
return nil
}
// TransferFractionalBalances migrates fractional balances from x/evmutil to
// x/precisebank. It sets the fractional balance in x/precisebank and deletes
// the account from x/evmutil. Returns the aggregate sum of all fractional
// balances.
func TransferFractionalBalances(
ctx sdk.Context,
evmutilKeeper evmutilkeeper.Keeper,
precisebankKeeper precisebankkeeper.Keeper,
) (sdkmath.Int, error) {
aggregateSum := sdkmath.ZeroInt()
var iterErr error
evmutilKeeper.IterateAllAccounts(ctx, func(acc evmutiltypes.Account) bool {
// Set account balance in x/precisebank
precisebankKeeper.SetFractionalBalance(ctx, acc.Address, acc.Balance)
// Delete account from x/evmutil
iterErr := evmutilKeeper.SetAccount(ctx, evmutiltypes.Account{
Address: acc.Address,
// Set balance to 0 to delete it
Balance: sdkmath.ZeroInt(),
})
// Halt iteration if there was an error
if iterErr != nil {
return true
}
// Aggregate sum of all fractional balances
aggregateSum = aggregateSum.Add(acc.Balance)
// Continue iterating
return false
})
return aggregateSum, iterErr
}
// InitializeRemainder initializes the remainder amount in x/precisebank. It
// calculates the remainder amount that is needed to ensure that the sum of all
// fractional balances is a multiple of the conversion factor. The remainder
// amount is stored in the store and returned.
func InitializeRemainder(
ctx sdk.Context,
precisebankKeeper precisebankkeeper.Keeper,
aggregateSum sdkmath.Int,
) sdkmath.Int {
// Extra fractional coins that exceed the conversion factor.
// This extra + remainder should equal the conversion factor to ensure
// (sum(fBalances) + remainder) % conversionFactor = 0
extraFractionalAmount := aggregateSum.Mod(precisebanktypes.ConversionFactor())
remainder := precisebanktypes.ConversionFactor().
Sub(extraFractionalAmount).
// Mod conversion factor to ensure remainder is valid.
// If extraFractionalAmount is a multiple of conversion factor, the
// remainder is 0.
Mod(precisebanktypes.ConversionFactor())
// Panics if the remainder is invalid. In a correct chain state and only
// mint/burns due to transfers, this would be 0.
precisebankKeeper.SetRemainderAmount(ctx, remainder)
return remainder
}
// TransferFractionalBalanceReserve migrates the fractional balance reserve from
// x/evmutil to x/precisebank. It transfers the reserve balance from x/evmutil
// to x/precisebank and ensures that the reserve fully backs all fractional
// balances. It mints or burns coins to back the fractional balances exactly.
func TransferFractionalBalanceReserve(
ctx sdk.Context,
accountKeeper evmutiltypes.AccountKeeper,
bankKeeper bankkeeper.Keeper,
precisebankKeeper precisebankkeeper.Keeper,
) error {
logger := ctx.Logger()
// Transfer x/evmutil reserve to x/precisebank.
evmutilAddr := accountKeeper.GetModuleAddress(evmutiltypes.ModuleName)
reserveBalance := bankKeeper.GetBalance(ctx, evmutilAddr, precisebanktypes.IntegerCoinDenom)
if err := bankKeeper.SendCoinsFromModuleToModule(
ctx,
evmutiltypes.ModuleName, // from x/evmutil
precisebanktypes.ModuleName, // to x/precisebank
sdk.NewCoins(reserveBalance),
); err != nil {
return fmt.Errorf("failed to transfer reserve from x/evmutil to x/precisebank: %w", err)
}
logger.Info(fmt.Sprintf("transferred reserve balance: %s", reserveBalance))
// Ensure x/precisebank reserve fully backs all fractional balances.
totalFractionalBalances := precisebankKeeper.GetTotalSumFractionalBalances(ctx)
// Does NOT ensure state is correct, total fractional balances should be a
// multiple of conversion factor but is not guaranteed due to the remainder.
// Remainder initialization is handled by InitializeRemainder.
// Determine how much the reserve is off by, e.g. unbacked amount
expectedReserveBalance := totalFractionalBalances.Quo(precisebanktypes.ConversionFactor())
// If there is a remainder (totalFractionalBalances % conversionFactor != 0),
// then expectedReserveBalance is rounded up to the nearest integer.
if totalFractionalBalances.Mod(precisebanktypes.ConversionFactor()).IsPositive() {
expectedReserveBalance = expectedReserveBalance.Add(sdkmath.OneInt())
}
unbackedAmount := expectedReserveBalance.Sub(reserveBalance.Amount)
logger.Info(fmt.Sprintf("total account fractional balances: %s", totalFractionalBalances))
// Three possible cases:
// 1. Reserve is not enough, mint coins to back the fractional balances
// 2. Reserve is too much, burn coins to back the fractional balances exactly
// 3. Reserve is exactly enough, no action needed
if unbackedAmount.IsPositive() {
coins := sdk.NewCoins(sdk.NewCoin(precisebanktypes.IntegerCoinDenom, unbackedAmount))
if err := bankKeeper.MintCoins(ctx, precisebanktypes.ModuleName, coins); err != nil {
return fmt.Errorf("failed to mint extra reserve coins: %w", err)
}
logger.Info(fmt.Sprintf("unbacked amount minted to reserve: %s", unbackedAmount))
} else if unbackedAmount.IsNegative() {
coins := sdk.NewCoins(sdk.NewCoin(precisebanktypes.IntegerCoinDenom, unbackedAmount.Neg()))
if err := bankKeeper.BurnCoins(ctx, precisebanktypes.ModuleName, coins); err != nil {
return fmt.Errorf("failed to burn extra reserve coins: %w", err)
}
logger.Info(fmt.Sprintf("extra reserve amount burned: %s", unbackedAmount.Neg()))
} else {
logger.Info("reserve exactly backs fractional balances, no mint/burn needed")
}
return nil
}

434
app/upgrades_test.go Normal file
View File

@ -0,0 +1,434 @@
package app_test
import (
"strconv"
"testing"
"time"
sdkmath "cosmossdk.io/math"
"github.com/0glabs/0g-chain/app"
evmutiltypes "github.com/0glabs/0g-chain/x/evmutil/types"
precisebankkeeper "github.com/0glabs/0g-chain/x/precisebank/keeper"
precisebanktypes "github.com/0glabs/0g-chain/x/precisebank/types"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
)
func TestMigrateEvmutilToPrecisebank(t *testing.T) {
// Full test case with all components together
tests := []struct {
name string
initialReserve sdkmath.Int
fractionalBalances []sdkmath.Int
}{
{
"no fractional balances",
sdkmath.NewInt(0),
[]sdkmath.Int{},
},
{
"sufficient reserve, 0 remainder",
// Accounts adding up to 2 int units, same as reserve
sdkmath.NewInt(2),
[]sdkmath.Int{
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
},
},
{
"insufficient reserve, 0 remainder",
// Accounts adding up to 2 int units, but only 1 int unit in reserve
sdkmath.NewInt(1),
[]sdkmath.Int{
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
},
},
{
"excess reserve, 0 remainder",
// Accounts adding up to 2 int units, but 3 int unit in reserve
sdkmath.NewInt(3),
[]sdkmath.Int{
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
},
},
{
"sufficient reserve, non-zero remainder",
// Accounts adding up to 1.5 int units, same as reserve
sdkmath.NewInt(2),
[]sdkmath.Int{
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
},
},
{
"insufficient reserve, non-zero remainder",
// Accounts adding up to 1.5 int units, less than reserve,
// Reserve should be 2 and remainder 0.5
sdkmath.NewInt(1),
[]sdkmath.Int{
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
},
},
{
"excess reserve, non-zero remainder",
// Accounts adding up to 1.5 int units, 3 int units in reserve
sdkmath.NewInt(3),
[]sdkmath.Int{
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tApp := app.NewTestApp()
tApp.InitializeFromGenesisStates()
ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: time.Now()})
ak := tApp.GetAccountKeeper()
bk := tApp.GetBankKeeper()
evmuk := tApp.GetEvmutilKeeper()
pbk := tApp.GetPrecisebankKeeper()
reserveCoin := sdk.NewCoin(precisebanktypes.IntegerCoinDenom, tt.initialReserve)
err := bk.MintCoins(ctx, evmutiltypes.ModuleName, sdk.NewCoins(reserveCoin))
require.NoError(t, err)
oldReserveAddr := tApp.GetAccountKeeper().GetModuleAddress(evmutiltypes.ModuleName)
newReserveAddr := tApp.GetAccountKeeper().GetModuleAddress(precisebanktypes.ModuleName)
// Double check balances
oldReserveBalance := bk.GetBalance(ctx, oldReserveAddr, precisebanktypes.IntegerCoinDenom)
newReserveBalance := bk.GetBalance(ctx, newReserveAddr, precisebanktypes.IntegerCoinDenom)
require.Equal(t, tt.initialReserve, oldReserveBalance.Amount, "initial x/evmutil reserve balance")
require.True(t, newReserveBalance.IsZero(), "empty initial new reserve")
// Set accounts
for i, balance := range tt.fractionalBalances {
addr := sdk.AccAddress([]byte(strconv.Itoa(i)))
err := evmuk.SetBalance(ctx, addr, balance)
require.NoError(t, err)
}
// Run full x/evmutil -> x/precisebank migration
err = app.MigrateEvmutilToPrecisebank(
ctx,
ak,
bk,
evmuk,
pbk,
)
require.NoError(t, err)
// Check old reserve is empty
oldReserveBalanceAfter := bk.GetBalance(ctx, oldReserveAddr, precisebanktypes.IntegerCoinDenom)
require.True(t, oldReserveBalanceAfter.IsZero(), "old reserve should be empty")
// Check new reserve fully backs fractional balances
newReserveBalanceAfter := bk.GetBalance(ctx, newReserveAddr, precisebanktypes.IntegerCoinDenom)
fractionalBalanceTotal := pbk.GetTotalSumFractionalBalances(ctx)
remainder := pbk.GetRemainderAmount(ctx)
expectedReserveBal := fractionalBalanceTotal.Add(remainder)
require.Equal(
t,
expectedReserveBal,
newReserveBalanceAfter.Amount.Mul(precisebanktypes.ConversionFactor()),
"new reserve should equal total fractional balances",
)
// Check balances are deleted in evmutil and migrated to precisebank
for i := range tt.fractionalBalances {
addr := sdk.AccAddress([]byte(strconv.Itoa(i)))
acc := evmuk.GetAccount(ctx, addr)
require.Nil(t, acc, "account should be deleted")
balance := pbk.GetFractionalBalance(ctx, addr)
require.Equal(t, tt.fractionalBalances[i], balance, "balance should be migrated")
}
// Checks balances valid and remainder
res, stop := precisebankkeeper.AllInvariants(pbk)(ctx)
require.Falsef(t, stop, "invariants should pass: %s", res)
})
}
}
func TestTransferFractionalBalances(t *testing.T) {
tests := []struct {
name string
fractionalBalances []sdkmath.Int
}{
{
"no fractional balances",
[]sdkmath.Int{},
},
{
"balanced fractional balances",
[]sdkmath.Int{
// 4 accounts
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
},
},
{
"unbalanced balances",
[]sdkmath.Int{
// 3 accounts
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tApp := app.NewTestApp()
tApp.InitializeFromGenesisStates()
ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: time.Now()})
evmutilk := tApp.GetEvmutilKeeper()
pbk := tApp.GetPrecisebankKeeper()
for i, balance := range tt.fractionalBalances {
addr := sdk.AccAddress([]byte(strconv.Itoa(i)))
err := evmutilk.SetBalance(ctx, addr, balance)
require.NoError(t, err)
}
// Run balance transfer
aggregateSum, err := app.TransferFractionalBalances(
ctx,
evmutilk,
pbk,
)
require.NoError(t, err)
// Check balances are deleted in evmutil and migrated to precisebank
sum := sdkmath.ZeroInt()
for i := range tt.fractionalBalances {
sum = sum.Add(tt.fractionalBalances[i])
addr := sdk.AccAddress([]byte(strconv.Itoa(i)))
acc := evmutilk.GetAccount(ctx, addr)
require.Nil(t, acc, "account should be deleted")
balance := pbk.GetFractionalBalance(ctx, addr)
require.Equal(t, tt.fractionalBalances[i], balance, "balance should be migrated")
}
require.Equal(t, sum, aggregateSum, "aggregate sum should be correct")
})
}
}
func TestInitializeRemainder(t *testing.T) {
tests := []struct {
name string
giveAggregateSum sdkmath.Int
wantRemainder sdkmath.Int
}{
{
"0 remainder, 1ukava",
precisebanktypes.ConversionFactor(),
sdkmath.NewInt(0),
},
{
"0 remainder, multiple ukava",
precisebanktypes.ConversionFactor().MulRaw(5),
sdkmath.NewInt(0),
},
{
"non-zero remainder, min",
precisebanktypes.ConversionFactor().SubRaw(1),
sdkmath.NewInt(1),
},
{
"non-zero remainder, max",
sdkmath.NewInt(1),
precisebanktypes.ConversionFactor().SubRaw(1),
},
{
"non-zero remainder, half",
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tApp := app.NewTestApp()
tApp.InitializeFromGenesisStates()
pbk := tApp.GetPrecisebankKeeper()
ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: time.Now()})
remainder := app.InitializeRemainder(
ctx,
tApp.GetPrecisebankKeeper(),
tt.giveAggregateSum,
)
require.Equal(t, tt.wantRemainder, remainder)
// Check actual state
remainderAfter := pbk.GetRemainderAmount(ctx)
require.Equal(t, tt.wantRemainder, remainderAfter)
// Not checking invariants here since it requires actual balance state
aggregateSumWithRemainder := tt.giveAggregateSum.Add(remainder)
require.True(
t,
aggregateSumWithRemainder.
Mod(precisebanktypes.ConversionFactor()).
IsZero(),
"remainder + aggregate sum should be a multiple of the conversion factor",
)
})
}
}
func TestTransferFractionalBalanceReserve(t *testing.T) {
tests := []struct {
name string
initialReserve sdk.Coin
fractionalBalances []sdkmath.Int
}{
{
"balanced reserve, no remainder",
sdk.NewCoin(precisebanktypes.IntegerCoinDenom, sdk.NewInt(1)),
[]sdkmath.Int{
// 2 accounts
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
},
},
{
"insufficient reserve",
sdk.NewCoin(precisebanktypes.IntegerCoinDenom, sdk.NewInt(1)),
[]sdkmath.Int{
// 4 accounts, total 2 int units
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
},
},
{
"extra reserve funds",
sdk.NewCoin(precisebanktypes.IntegerCoinDenom, sdk.NewInt(2)),
[]sdkmath.Int{
// 2 accounts, total 1 int units
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
},
},
{
"insufficient reserve, with remainder",
sdk.NewCoin(precisebanktypes.IntegerCoinDenom, sdk.NewInt(1)),
[]sdkmath.Int{
// 5 accounts, total 2.5 int units
// Expected 3 int units in reserve, 0.5 remainder
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
},
},
{
"extra reserve funds, with remainder",
sdk.NewCoin(precisebanktypes.IntegerCoinDenom, sdk.NewInt(3)),
[]sdkmath.Int{
// 3 accounts, total 1.5 int units.
// Expected 2 int units in reserve, 0.5 remainder
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
precisebanktypes.ConversionFactor().QuoRaw(2),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tApp := app.NewTestApp()
tApp.InitializeFromGenesisStates()
ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: time.Now()})
bk := tApp.GetBankKeeper()
pbk := tApp.GetPrecisebankKeeper()
err := bk.MintCoins(ctx, evmutiltypes.ModuleName, sdk.NewCoins(tt.initialReserve))
require.NoError(t, err)
oldReserveAddr := tApp.GetAccountKeeper().GetModuleAddress(evmutiltypes.ModuleName)
newReserveAddr := tApp.GetAccountKeeper().GetModuleAddress(precisebanktypes.ModuleName)
// Double check balances
oldReserveBalance := bk.GetBalance(ctx, oldReserveAddr, precisebanktypes.IntegerCoinDenom)
newReserveBalance := bk.GetBalance(ctx, newReserveAddr, precisebanktypes.IntegerCoinDenom)
require.Equal(t, tt.initialReserve, oldReserveBalance)
require.True(t, newReserveBalance.IsZero(), "empty initial new reserve")
for i, balance := range tt.fractionalBalances {
addr := sdk.AccAddress([]byte{byte(i)})
require.NotPanics(t, func() {
pbk.SetFractionalBalance(ctx, addr, balance)
}, "given fractional balances should be valid")
}
// Run reserve migration
err = app.TransferFractionalBalanceReserve(
ctx,
tApp.GetAccountKeeper(),
bk,
tApp.GetPrecisebankKeeper(),
)
require.NoError(t, err)
// Check old reserve is empty
oldReserveBalanceAfter := bk.GetBalance(ctx, oldReserveAddr, precisebanktypes.IntegerCoinDenom)
require.True(t, oldReserveBalanceAfter.IsZero(), "old reserve should be empty")
// Check new reserve fully backs fractional balances
newReserveBalanceAfter := bk.GetBalance(ctx, newReserveAddr, precisebanktypes.IntegerCoinDenom)
fractionalBalanceTotal := pbk.GetTotalSumFractionalBalances(ctx)
expectedReserveBal := fractionalBalanceTotal.
Quo(precisebanktypes.ConversionFactor())
// Check if theres a remainder
if fractionalBalanceTotal.Mod(precisebanktypes.ConversionFactor()).IsPositive() {
expectedReserveBal = expectedReserveBal.Add(sdkmath.OneInt())
}
require.Equal(
t,
expectedReserveBal,
newReserveBalanceAfter.Amount,
"new reserve should equal total fractional balances + remainder",
)
})
}
}

45
build/lint.mk Normal file
View File

@ -0,0 +1,45 @@
################################################################################
### Required Variables ###
################################################################################
ifndef DOCKER
$(error DOCKER not set)
endif
ifndef BUILD_DIR
$(error BUILD_DIR not set)
endif
################################################################################
### Lint Settings ###
################################################################################
LINT_FROM_REV ?= $(shell git merge-base origin/master HEAD)
GOLANGCI_VERSION ?= $(shell cat .golangci-version)
GOLANGCI_IMAGE_TAG ?= golangci/golangci-lint:$(GOLANGCI_VERSION)
GOLANGCI_DIR ?= $(CURDIR)/$(BUILD_DIR)/.golangci-lint
GOLANGCI_CACHE_DIR ?= $(GOLANGCI_DIR)/$(GOLANGCI_VERSION)-cache
GOLANGCI_MOD_CACHE_DIR ?= $(GOLANGCI_DIR)/go-mod
################################################################################
### Lint Target ###
################################################################################
.PHONY: lint
lint: $(GOLANGCI_CACHE_DIR) $(GOLANGCI_MOD_CACHE_DIR)
@echo "Running lint from rev $(LINT_FROM_REV), use LINT_FROM_REV var to override."
$(DOCKER) run -t --rm \
-v $(GOLANGCI_CACHE_DIR):/root/.cache \
-v $(GOLANGCI_MOD_CACHE_DIR):/go/pkg/mod \
-v $(CURDIR):/app \
-w /app \
$(GOLANGCI_IMAGE_TAG) \
golangci-lint run -v --new-from-rev $(LINT_FROM_REV)
$(GOLANGCI_CACHE_DIR):
@mkdir -p $@
$(GOLANGCI_MOD_CACHE_DIR):
@mkdir -p $@

View File

@ -56,6 +56,7 @@ proto-update-deps: check-rsync ## Update all third party proto files
@mkdir -p client/docs @mkdir -p client/docs
@cp -f $(COSMOS_SDK_PATH)/client/docs/swagger-ui/swagger.yaml client/docs/cosmos-swagger.yml @cp -f $(COSMOS_SDK_PATH)/client/docs/swagger-ui/swagger.yaml client/docs/cosmos-swagger.yml
@cp -f $(IBC_GO_PATH)/docs/client/swagger-ui/swagger.yaml client/docs/ibc-go-swagger.yml @cp -f $(IBC_GO_PATH)/docs/client/swagger-ui/swagger.yaml client/docs/ibc-go-swagger.yml
@cp -f $(ETHERMINT_PATH)/client/docs/swagger-ui/swagger.yaml client/docs/ethermint-swagger.yml
@mkdir -p $(COSMOS_PROTO_TYPES) @mkdir -p $(COSMOS_PROTO_TYPES)
@cp -f $(COSMOS_PROTO_PATH)/proto/cosmos_proto/cosmos.proto $(COSMOS_PROTO_TYPES)/cosmos.proto @cp -f $(COSMOS_PROTO_PATH)/proto/cosmos_proto/cosmos.proto $(COSMOS_PROTO_TYPES)/cosmos.proto

View File

@ -1 +1 @@
a967d2fdda299ec8e1e3b99fb55bd06ecfdb0469 6862cde560c70cb82f7908e6cef22ca223465bd2

View File

@ -22,6 +22,8 @@
}, },
"app_hash": "", "app_hash": "",
"app_state": { "app_state": {
"06-solomachine": null,
"07-tendermint": null,
"auction": { "auction": {
"next_auction_id": "1", "next_auction_id": "1",
"params": { "params": {
@ -505,6 +507,10 @@
{ {
"address": "kava1vlpsrmdyuywvaqrv7rx6xga224sqfwz3fyfhwq", "address": "kava1vlpsrmdyuywvaqrv7rx6xga224sqfwz3fyfhwq",
"coins": [ "coins": [
{
"denom": "bnb",
"amount": "500000000"
},
{ {
"denom": "btcb", "denom": "btcb",
"amount": "200000000" "amount": "200000000"
@ -525,6 +531,10 @@
"denom": "erc20/axelar/wbtc", "denom": "erc20/axelar/wbtc",
"amount": "1000000000" "amount": "1000000000"
}, },
{
"denom": "erc20/bitgo/wbtc",
"amount": "200000000"
},
{ {
"denom": "erc20/multichain/usdc", "denom": "erc20/multichain/usdc",
"amount": "1000000000000000000" "amount": "1000000000000000000"
@ -556,12 +566,20 @@
{ {
"denom": "usdx", "denom": "usdx",
"amount": "103000000000" "amount": "103000000000"
},
{
"denom": "xrpb",
"amount": "1000000000000000"
} }
] ]
}, },
{ {
"address": "kava1krh7k30pc9rteejpl2zycj0vau58y8c69xkzws", "address": "kava1krh7k30pc9rteejpl2zycj0vau58y8c69xkzws",
"coins": [ "coins": [
{
"denom": "bnb",
"amount": "100000000000000000"
},
{ {
"denom": "btcb", "denom": "btcb",
"amount": "200000000" "amount": "200000000"
@ -582,6 +600,10 @@
"denom": "erc20/axelar/wbtc", "denom": "erc20/axelar/wbtc",
"amount": "1000000000" "amount": "1000000000"
}, },
{
"denom": "erc20/bitgo/wbtc",
"amount": "200000000"
},
{ {
"denom": "erc20/tether/usdt", "denom": "erc20/tether/usdt",
"amount": "100000000000" "amount": "100000000000"
@ -601,6 +623,10 @@
{ {
"denom": "usdx", "denom": "usdx",
"amount": "103000000000" "amount": "103000000000"
},
{
"denom": "xrpb",
"amount": "103000000000"
} }
] ]
}, },
@ -822,6 +848,7 @@
"gov_denom": "ukava", "gov_denom": "ukava",
"params": { "params": {
"circuit_breaker": false, "circuit_breaker": false,
"liquidation_block_interval": 500,
"collateral_params": [ "collateral_params": [
{ {
"denom": "bnb", "denom": "bnb",
@ -993,8 +1020,7 @@
"check_collateralization_index_count": "10", "check_collateralization_index_count": "10",
"conversion_factor": "6" "conversion_factor": "6"
} }
] ],
,
"debt_auction_lot": "10000000000", "debt_auction_lot": "10000000000",
"debt_auction_threshold": "100000000000", "debt_auction_threshold": "100000000000",
"debt_param": { "debt_param": {
@ -1241,7 +1267,15 @@
"votes": [] "votes": []
}, },
"community": { "community": {
"params": {} "params": {
"upgrade_time_disable_inflation": "2023-11-01T00:00:00Z",
"upgrade_time_set_staking_rewards_per_second": "744191",
"staking_rewards_per_second": "0"
},
"staking_rewards_state": {
"last_accumulation_time": "0001-01-01T00:00:00Z",
"last_truncation_error": "0"
}
}, },
"crisis": { "crisis": {
"constant_fee": { "constant_fee": {
@ -2067,6 +2101,25 @@
} }
], ],
"nested_types": [] "nested_types": []
},
{
"msg_type_url": "/kava.committee.v1beta1.MsgVote",
"msg_value_type_name": "MsgValueCommitteeVote",
"value_types": [
{
"name": "proposal_id",
"type": "uint64"
},
{
"name": "voter",
"type": "string"
},
{
"name": "vote_type",
"type": "int32"
}
],
"nested_types": []
} }
], ],
"allow_unprotected_txs": false "allow_unprotected_txs": false
@ -2229,22 +2282,27 @@
"deposits": [], "deposits": [],
"votes": [], "votes": [],
"proposals": [], "proposals": [],
"deposit_params": { "deposit_params": null,
"voting_params": {
"voting_period": "604800s"
},
"tally_params": null,
"params": {
"min_deposit": [ "min_deposit": [
{ {
"denom": "ukava", "denom": "ukava",
"amount": "10000000" "amount": "10000000"
} }
], ],
"max_deposit_period": "172800s" "max_deposit_period": "172800s",
}, "voting_period": "604800s",
"voting_params": {
"voting_period": "600s"
},
"tally_params": {
"quorum": "0.334000000000000000", "quorum": "0.334000000000000000",
"threshold": "0.500000000000000000", "threshold": "0.500000000000000000",
"veto_threshold": "0.334000000000000000" "veto_threshold": "0.334000000000000000",
"min_initial_deposit_ratio": "0.000000000000000000",
"burn_vote_quorum": false,
"burn_proposal_deposit_prevote": false,
"burn_vote_veto": true
} }
}, },
"hard": { "hard": {
@ -2519,6 +2577,24 @@
}, },
"reserve_factor": "0.025000000000000000", "reserve_factor": "0.025000000000000000",
"keeper_reward_percentage": "0.020000000000000000" "keeper_reward_percentage": "0.020000000000000000"
},
{
"denom": "erc20/bitgo/wbtc",
"borrow_limit": {
"has_max_limit": true,
"maximum_limit": "0.000000000000000000",
"loan_to_value": "0.000000000000000000"
},
"spot_market_id": "btc:usd:30",
"conversion_factor": "100000000",
"interest_rate_model": {
"base_rate_apy": "0.000000000000000000",
"base_multiplier": "0.050000000000000000",
"kink": "0.800000000000000000",
"jump_multiplier": "5.000000000000000000"
},
"reserve_factor": "0.025000000000000000",
"keeper_reward_percentage": "0.020000000000000000"
} }
], ],
"minimum_borrow_usd_value": "10.000000000000000000" "minimum_borrow_usd_value": "10.000000000000000000"
@ -2734,6 +2810,18 @@
"amount": "787" "amount": "787"
} }
] ]
},
{
"active": true,
"collateral_type": "erc20/bitgo/wbtc",
"start": "2022-11-11T15:00:00Z",
"end": "2025-11-11T15:00:00Z",
"rewards_per_second": [
{
"denom": "ukava",
"amount": "787"
}
]
} }
], ],
"hard_borrow_reward_periods": [], "hard_borrow_reward_periods": [],
@ -3170,6 +3258,16 @@
} }
}, },
"params": null, "params": null,
"packetfowardmiddleware": {
"params": {
"fee_percentage": "0.000000000000000000"
},
"in_flight_packets": {}
},
"precisebank": {
"balances": [],
"remainder": "0"
},
"pricefeed": { "pricefeed": {
"params": { "params": {
"markets": [ "markets": [
@ -3643,6 +3741,7 @@
} }
] ]
}, },
"router": {},
"savings": { "savings": {
"params": { "params": {
"supported_denoms": [ "supported_denoms": [
@ -3814,7 +3913,8 @@
"params": { "params": {
"send_enabled": true, "send_enabled": true,
"receive_enabled": true "receive_enabled": true
} },
"total_escrowed": []
}, },
"upgrade": {}, "upgrade": {},
"validatorvesting": null, "validatorvesting": null,

View File

@ -3006,6 +3006,9 @@
}, },
"in_flight_packets": {} "in_flight_packets": {}
}, },
"precisebank": {
"remainder": "0"
},
"pricefeed": { "pricefeed": {
"params": { "params": {
"markets": [ "markets": [

View File

@ -182,6 +182,23 @@
] ]
} }
}, },
{
"url": "./out/swagger/kava/precisebank/v1/query.swagger.json",
"tags": {
"rename": {
"Query": "Precisebank"
}
},
"operationIds": {
"rename": [
{
"type": "regex",
"from": "(.*)",
"to": "Precisebank$1"
}
]
}
},
{ {
"url": "./out/swagger/kava/pricefeed/v1beta1/query.swagger.json", "url": "./out/swagger/kava/pricefeed/v1beta1/query.swagger.json",
"tags": { "tags": {
@ -295,6 +312,30 @@
] ]
} }
}, },
{
"url": "./client/docs/ethermint-swagger.yml",
"dereference": {
"circular": "ignore"
},
"tags": {
"rename": {
"Query": "Ethermint"
}
},
"operationIds": {
"rename": [
{
"type": "regex",
"from": "(.*)",
"to": "Ethermint$1"
}
]
},
"paths": {
"exclude": [
]
}
},
{ {
"url": "./client/docs/legacy-swagger.yml", "url": "./client/docs/legacy-swagger.yml",
"dereference": { "dereference": {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,381 @@
[
{
"inputs": [
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "string",
"name": "symbol",
"type": "string"
},
{
"internalType": "uint8",
"name": "decimals_",
"type": "uint8"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "burn",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "decimals",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "subtractedValue",
"type": "uint256"
}
],
"name": "decreaseAllowance",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "addedValue",
"type": "uint256"
}
],
"name": "increaseAllowance",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "mint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]

File diff suppressed because one or more lines are too long

1069
client/erc20/main.go Normal file

File diff suppressed because one or more lines are too long

View File

@ -6,6 +6,8 @@ import (
"fmt" "fmt"
"net/url" "net/url"
"github.com/0glabs/0g-chain/app"
"github.com/cosmos/cosmos-sdk/codec"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/credentials/insecure"
@ -28,8 +30,20 @@ func newGrpcConnection(ctx context.Context, endpoint string) (*grpc.ClientConn,
return nil, fmt.Errorf("unknown grpc url scheme: %s", grpcUrl.Scheme) return nil, fmt.Errorf("unknown grpc url scheme: %s", grpcUrl.Scheme)
} }
// Ensure the encoding config is set up correctly with the query client
// otherwise it will produce panics like:
// invalid Go type math.Int for field ...
encodingConfig := app.MakeEncodingConfig()
protoCodec := codec.NewProtoCodec(encodingConfig.InterfaceRegistry)
grpcCodec := protoCodec.GRPCCodec()
secureOpt := grpc.WithTransportCredentials(creds) secureOpt := grpc.WithTransportCredentials(creds)
grpcConn, err := grpc.DialContext(ctx, grpcUrl.Host, secureOpt) grpcConn, err := grpc.DialContext(
ctx,
grpcUrl.Host,
secureOpt,
grpc.WithDefaultCallOptions(grpc.ForceCodec(grpcCodec)),
)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -28,6 +28,7 @@ import (
committeetypes "github.com/0glabs/0g-chain/x/committee/types" committeetypes "github.com/0glabs/0g-chain/x/committee/types"
evmutiltypes "github.com/0glabs/0g-chain/x/evmutil/types" evmutiltypes "github.com/0glabs/0g-chain/x/evmutil/types"
issuancetypes "github.com/0glabs/0g-chain/x/issuance/types" issuancetypes "github.com/0glabs/0g-chain/x/issuance/types"
precisebanktypes "github.com/0glabs/0g-chain/x/precisebank/types"
pricefeedtypes "github.com/0glabs/0g-chain/x/pricefeed/types" pricefeedtypes "github.com/0glabs/0g-chain/x/pricefeed/types"
) )
@ -65,6 +66,7 @@ type QueryClient struct {
Evmutil evmutiltypes.QueryClient Evmutil evmutiltypes.QueryClient
Issuance issuancetypes.QueryClient Issuance issuancetypes.QueryClient
Pricefeed pricefeedtypes.QueryClient Pricefeed pricefeedtypes.QueryClient
Precisebank precisebanktypes.QueryClient
} }
// NewQueryClient creates a new QueryClient and initializes all the module query clients // NewQueryClient creates a new QueryClient and initializes all the module query clients
@ -100,6 +102,7 @@ func NewQueryClient(grpcEndpoint string) (*QueryClient, error) {
Evmutil: evmutiltypes.NewQueryClient(conn), Evmutil: evmutiltypes.NewQueryClient(conn),
Issuance: issuancetypes.NewQueryClient(conn), Issuance: issuancetypes.NewQueryClient(conn),
Pricefeed: pricefeedtypes.NewQueryClient(conn), Pricefeed: pricefeedtypes.NewQueryClient(conn),
Precisebank: precisebanktypes.NewQueryClient(conn),
} }
return client, nil return client, nil
} }

View File

@ -7,6 +7,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/Kava-Labs/opendb"
cometbftdb "github.com/cometbft/cometbft-db" cometbftdb "github.com/cometbft/cometbft-db"
"github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/libs/log"
tmtypes "github.com/cometbft/cometbft/types" tmtypes "github.com/cometbft/cometbft/types"
@ -63,7 +64,7 @@ func (ac appCreator) newApp(
homeDir := cast.ToString(appOpts.Get(flags.FlagHome)) homeDir := cast.ToString(appOpts.Get(flags.FlagHome))
snapshotDir := filepath.Join(homeDir, "data", "snapshots") // TODO can these directory names be imported from somewhere? snapshotDir := filepath.Join(homeDir, "data", "snapshots") // TODO can these directory names be imported from somewhere?
snapshotDB, err := cometbftdb.NewDB("metadata", server.GetAppDBBackend(appOpts), snapshotDir) snapshotDB, err := opendb.OpenDB(appOpts, snapshotDir, "metadata", server.GetAppDBBackend(appOpts))
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -31,10 +31,7 @@ func newDataCmd(opts ethermintserver.StartOptions) *cobra.Command {
} }
printKeys(tree) printKeys(tree)
hash, err := tree.Hash() hash := tree.Hash()
if err != nil {
return err
}
fmt.Printf("Hash: %X\n", hash) fmt.Printf("Hash: %X\n", hash)
fmt.Printf("Size: %X\n", tree.Size()) fmt.Printf("Size: %X\n", tree.Size())

View File

@ -28,11 +28,7 @@ func newHashCmd(opts ethermintserver.StartOptions) *cobra.Command {
return err return err
} }
hash, err := tree.Hash() fmt.Printf("Hash: %X\n", tree.Hash())
if err != nil {
return err
}
fmt.Printf("Hash: %X\n", hash)
return nil return nil
}, },

View File

@ -2,15 +2,19 @@ package iavlviewer
import ( import (
"fmt" "fmt"
"os"
"strconv" "strconv"
dbm "github.com/cometbft/cometbft-db" "cosmossdk.io/log"
dbm "github.com/cosmos/cosmos-db"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/store/wrapper"
ethermintserver "github.com/evmos/ethermint/server" ethermintserver "github.com/evmos/ethermint/server"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/cosmos/iavl" "github.com/cosmos/iavl"
iavldb "github.com/cosmos/iavl/db"
) )
const ( const (
@ -54,7 +58,9 @@ func openPrefixTree(opts ethermintserver.StartOptions, cmd *cobra.Command, prefi
} }
}() }()
tree, err := readTree(db, version, []byte(prefix)) cosmosdb := wrapper.NewCosmosDB(db)
tree, err := readTree(cosmosdb, version, []byte(prefix))
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read tree with prefix %s: %s", prefix, err) return nil, fmt.Errorf("failed to read tree with prefix %s: %s", prefix, err)
} }
@ -69,10 +75,7 @@ func readTree(db dbm.DB, version int, prefix []byte) (*iavl.MutableTree, error)
db = dbm.NewPrefixDB(db, prefix) db = dbm.NewPrefixDB(db, prefix)
} }
tree, err := iavl.NewMutableTree(db, DefaultCacheSize, false) tree := iavl.NewMutableTree(iavldb.NewWrapper(db), DefaultCacheSize, false, log.NewLogger(os.Stdout))
if err != nil {
return nil, err
}
ver, err := tree.LoadVersion(int64(version)) ver, err := tree.LoadVersion(int64(version))
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -14,14 +14,14 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/0glabs/0g-chain/cmd/opendb" "github.com/cometbft/cometbft/libs/log"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server"
"github.com/linxGnu/grocksdb" "github.com/linxGnu/grocksdb"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
"github.com/cometbft/cometbft/libs/log" "github.com/Kava-Labs/opendb"
) )
const ( const (

View File

@ -3,16 +3,18 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"path/filepath"
dbm "github.com/cometbft/cometbft-db"
tmcfg "github.com/cometbft/cometbft/config"
tmcli "github.com/cometbft/cometbft/libs/cli"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/config" "github.com/cosmos/cosmos-sdk/client/config"
"github.com/cosmos/cosmos-sdk/client/debug" "github.com/cosmos/cosmos-sdk/client/debug"
"github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
tmcfg "github.com/cometbft/cometbft/config"
tmcli "github.com/cometbft/cometbft/libs/cli"
"github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/genutil" "github.com/cosmos/cosmos-sdk/x/genutil"
@ -29,8 +31,8 @@ import (
"github.com/0glabs/0g-chain/chaincfg" "github.com/0glabs/0g-chain/chaincfg"
"github.com/0glabs/0g-chain/cmd/0gchaind/iavlviewer" "github.com/0glabs/0g-chain/cmd/0gchaind/iavlviewer"
"github.com/0glabs/0g-chain/cmd/0gchaind/rocksdb" "github.com/0glabs/0g-chain/cmd/0gchaind/rocksdb"
"github.com/0glabs/0g-chain/cmd/opendb"
"github.com/0glabs/0g-chain/crypto/vrf" "github.com/0glabs/0g-chain/crypto/vrf"
"github.com/Kava-Labs/opendb"
) )
func customKeyringOptions() keyring.Option { func customKeyringOptions() keyring.Option {
@ -52,7 +54,7 @@ func NewRootCmd() *cobra.Command {
WithAccountRetriever(types.AccountRetriever{}). WithAccountRetriever(types.AccountRetriever{}).
WithBroadcastMode(flags.FlagBroadcastMode). WithBroadcastMode(flags.FlagBroadcastMode).
WithHomeDir(chaincfg.DefaultNodeHome). WithHomeDir(chaincfg.DefaultNodeHome).
WithKeyringOptions(customKeyringOptions()). WithKeyringOptions(hd.EthSecp256k1Option()).
WithViper(chaincfg.EnvPrefix) WithViper(chaincfg.EnvPrefix)
rootCmd := &cobra.Command{ rootCmd := &cobra.Command{
Use: chaincfg.AppName, Use: chaincfg.AppName,
@ -90,7 +92,14 @@ func NewRootCmd() *cobra.Command {
return rootCmd return rootCmd
} }
// addSubCmds registers all the sub commands used by 0g-chain. // dbOpener is a function to open `application.db`, potentially with customized options.
// dbOpener sets dataDir to "data", dbName to "application" and calls generic OpenDB function.
func dbOpener(opts servertypes.AppOptions, rootDir string, backend dbm.BackendType) (dbm.DB, error) {
dataDir := filepath.Join(rootDir, "data")
return opendb.OpenDB(opts, dataDir, "application", backend)
}
// addSubCmds registers all the sub commands used by kava.
func addSubCmds(rootCmd *cobra.Command, encodingConfig params.EncodingConfig, defaultNodeHome string) { func addSubCmds(rootCmd *cobra.Command, encodingConfig params.EncodingConfig, defaultNodeHome string) {
gentxModule, ok := app.ModuleBasics[genutiltypes.ModuleName].(genutil.AppModuleBasic) gentxModule, ok := app.ModuleBasics[genutiltypes.ModuleName].(genutil.AppModuleBasic)
if !ok { if !ok {
@ -120,7 +129,7 @@ func addSubCmds(rootCmd *cobra.Command, encodingConfig params.EncodingConfig, de
opts := ethermintserver.StartOptions{ opts := ethermintserver.StartOptions{
AppCreator: ac.newApp, AppCreator: ac.newApp,
DefaultNodeHome: chaincfg.DefaultNodeHome, DefaultNodeHome: chaincfg.DefaultNodeHome,
DBOpener: opendb.OpenDB, DBOpener: dbOpener,
} }
// ethermintserver adds additional flags to start the JSON-RPC server for evm support // ethermintserver adds additional flags to start the JSON-RPC server for evm support
ethermintserver.AddCommands( ethermintserver.AddCommands(

View File

@ -219,11 +219,14 @@ func shardApplicationDb(multistore *rootmulti.Store, startBlock, endBlock int64)
} }
if len(pruneHeights) > 0 { if len(pruneHeights) > 0 {
// prune application state
fmt.Printf("pruning application state to height %d\n", startBlock) fmt.Printf("pruning application state to height %d\n", startBlock)
if err := multistore.PruneStores(true, pruneHeights); err != nil { for _, pruneHeight := range pruneHeights {
if err := multistore.PruneStores(pruneHeight); err != nil {
return fmt.Errorf("failed to prune application state: %s", err) return fmt.Errorf("failed to prune application state: %s", err)
} }
} }
}
return nil return nil
} }

View File

@ -1,499 +0,0 @@
//go:build rocksdb
// +build rocksdb
package opendb
import (
"github.com/go-kit/kit/metrics"
"github.com/go-kit/kit/metrics/prometheus"
stdprometheus "github.com/prometheus/client_golang/prometheus"
)
// rocksdbMetrics will be initialized in registerMetrics() if enableRocksdbMetrics flag set to true
var rocksdbMetrics *Metrics
// Metrics contains all rocksdb metrics which will be reported to prometheus
type Metrics struct {
// Keys
NumberKeysWritten metrics.Gauge
NumberKeysRead metrics.Gauge
NumberKeysUpdated metrics.Gauge
EstimateNumKeys metrics.Gauge
// Files
NumberFileOpens metrics.Gauge
NumberFileErrors metrics.Gauge
// Memory
BlockCacheUsage metrics.Gauge
EstimateTableReadersMem metrics.Gauge
CurSizeAllMemTables metrics.Gauge
BlockCachePinnedUsage metrics.Gauge
// Cache
BlockCacheMiss metrics.Gauge
BlockCacheHit metrics.Gauge
BlockCacheAdd metrics.Gauge
BlockCacheAddFailures metrics.Gauge
// Detailed Cache
BlockCacheIndexMiss metrics.Gauge
BlockCacheIndexHit metrics.Gauge
BlockCacheIndexBytesInsert metrics.Gauge
BlockCacheFilterMiss metrics.Gauge
BlockCacheFilterHit metrics.Gauge
BlockCacheFilterBytesInsert metrics.Gauge
BlockCacheDataMiss metrics.Gauge
BlockCacheDataHit metrics.Gauge
BlockCacheDataBytesInsert metrics.Gauge
// Latency
DBGetMicrosP50 metrics.Gauge
DBGetMicrosP95 metrics.Gauge
DBGetMicrosP99 metrics.Gauge
DBGetMicrosP100 metrics.Gauge
DBGetMicrosCount metrics.Gauge
DBWriteMicrosP50 metrics.Gauge
DBWriteMicrosP95 metrics.Gauge
DBWriteMicrosP99 metrics.Gauge
DBWriteMicrosP100 metrics.Gauge
DBWriteMicrosCount metrics.Gauge
// Write Stall
StallMicros metrics.Gauge
DBWriteStallP50 metrics.Gauge
DBWriteStallP95 metrics.Gauge
DBWriteStallP99 metrics.Gauge
DBWriteStallP100 metrics.Gauge
DBWriteStallCount metrics.Gauge
DBWriteStallSum metrics.Gauge
// Bloom Filter
BloomFilterUseful metrics.Gauge
BloomFilterFullPositive metrics.Gauge
BloomFilterFullTruePositive metrics.Gauge
// LSM Tree Stats
LastLevelReadBytes metrics.Gauge
LastLevelReadCount metrics.Gauge
NonLastLevelReadBytes metrics.Gauge
NonLastLevelReadCount metrics.Gauge
GetHitL0 metrics.Gauge
GetHitL1 metrics.Gauge
GetHitL2AndUp metrics.Gauge
}
// registerMetrics registers metrics in prometheus and initializes rocksdbMetrics variable
func registerMetrics() {
if rocksdbMetrics != nil {
// metrics already registered
return
}
labels := make([]string, 0)
rocksdbMetrics = &Metrics{
// Keys
NumberKeysWritten: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "key",
Name: "number_keys_written",
Help: "",
}, labels),
NumberKeysRead: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "key",
Name: "number_keys_read",
Help: "",
}, labels),
NumberKeysUpdated: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "key",
Name: "number_keys_updated",
Help: "",
}, labels),
EstimateNumKeys: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "key",
Name: "estimate_num_keys",
Help: "estimated number of total keys in the active and unflushed immutable memtables and storage",
}, labels),
// Files
NumberFileOpens: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "file",
Name: "number_file_opens",
Help: "",
}, labels),
NumberFileErrors: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "file",
Name: "number_file_errors",
Help: "",
}, labels),
// Memory
BlockCacheUsage: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "memory",
Name: "block_cache_usage",
Help: "memory size for the entries residing in block cache",
}, labels),
EstimateTableReadersMem: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "memory",
Name: "estimate_table_readers_mem",
Help: "estimated memory used for reading SST tables, excluding memory used in block cache (e.g., filter and index blocks)",
}, labels),
CurSizeAllMemTables: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "memory",
Name: "cur_size_all_mem_tables",
Help: "approximate size of active and unflushed immutable memtables (bytes)",
}, labels),
BlockCachePinnedUsage: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "memory",
Name: "block_cache_pinned_usage",
Help: "returns the memory size for the entries being pinned",
}, labels),
// Cache
BlockCacheMiss: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "cache",
Name: "block_cache_miss",
Help: "block_cache_miss == block_cache_index_miss + block_cache_filter_miss + block_cache_data_miss",
}, labels),
BlockCacheHit: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "cache",
Name: "block_cache_hit",
Help: "block_cache_hit == block_cache_index_hit + block_cache_filter_hit + block_cache_data_hit",
}, labels),
BlockCacheAdd: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "cache",
Name: "block_cache_add",
Help: "number of blocks added to block cache",
}, labels),
BlockCacheAddFailures: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "cache",
Name: "block_cache_add_failures",
Help: "number of failures when adding blocks to block cache",
}, labels),
// Detailed Cache
BlockCacheIndexMiss: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "detailed_cache",
Name: "block_cache_index_miss",
Help: "",
}, labels),
BlockCacheIndexHit: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "detailed_cache",
Name: "block_cache_index_hit",
Help: "",
}, labels),
BlockCacheIndexBytesInsert: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "detailed_cache",
Name: "block_cache_index_bytes_insert",
Help: "",
}, labels),
BlockCacheFilterMiss: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "detailed_cache",
Name: "block_cache_filter_miss",
Help: "",
}, labels),
BlockCacheFilterHit: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "detailed_cache",
Name: "block_cache_filter_hit",
Help: "",
}, labels),
BlockCacheFilterBytesInsert: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "detailed_cache",
Name: "block_cache_filter_bytes_insert",
Help: "",
}, labels),
BlockCacheDataMiss: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "detailed_cache",
Name: "block_cache_data_miss",
Help: "",
}, labels),
BlockCacheDataHit: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "detailed_cache",
Name: "block_cache_data_hit",
Help: "",
}, labels),
BlockCacheDataBytesInsert: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "detailed_cache",
Name: "block_cache_data_bytes_insert",
Help: "",
}, labels),
// Latency
DBGetMicrosP50: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "latency",
Name: "db_get_micros_p50",
Help: "",
}, labels),
DBGetMicrosP95: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "latency",
Name: "db_get_micros_p95",
Help: "",
}, labels),
DBGetMicrosP99: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "latency",
Name: "db_get_micros_p99",
Help: "",
}, labels),
DBGetMicrosP100: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "latency",
Name: "db_get_micros_p100",
Help: "",
}, labels),
DBGetMicrosCount: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "latency",
Name: "db_get_micros_count",
Help: "",
}, labels),
DBWriteMicrosP50: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "latency",
Name: "db_write_micros_p50",
Help: "",
}, labels),
DBWriteMicrosP95: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "latency",
Name: "db_write_micros_p95",
Help: "",
}, labels),
DBWriteMicrosP99: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "latency",
Name: "db_write_micros_p99",
Help: "",
}, labels),
DBWriteMicrosP100: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "latency",
Name: "db_write_micros_p100",
Help: "",
}, labels),
DBWriteMicrosCount: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "latency",
Name: "db_write_micros_count",
Help: "",
}, labels),
// Write Stall
StallMicros: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "stall",
Name: "stall_micros",
Help: "Writer has to wait for compaction or flush to finish.",
}, labels),
DBWriteStallP50: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "stall",
Name: "db_write_stall_p50",
Help: "",
}, labels),
DBWriteStallP95: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "stall",
Name: "db_write_stall_p95",
Help: "",
}, labels),
DBWriteStallP99: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "stall",
Name: "db_write_stall_p99",
Help: "",
}, labels),
DBWriteStallP100: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "stall",
Name: "db_write_stall_p100",
Help: "",
}, labels),
DBWriteStallCount: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "stall",
Name: "db_write_stall_count",
Help: "",
}, labels),
DBWriteStallSum: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "stall",
Name: "db_write_stall_sum",
Help: "",
}, labels),
// Bloom Filter
BloomFilterUseful: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "filter",
Name: "bloom_filter_useful",
Help: "number of times bloom filter has avoided file reads, i.e., negatives.",
}, labels),
BloomFilterFullPositive: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "filter",
Name: "bloom_filter_full_positive",
Help: "number of times bloom FullFilter has not avoided the reads.",
}, labels),
BloomFilterFullTruePositive: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "filter",
Name: "bloom_filter_full_true_positive",
Help: "number of times bloom FullFilter has not avoided the reads and data actually exist.",
}, labels),
// LSM Tree Stats
LastLevelReadBytes: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "lsm",
Name: "last_level_read_bytes",
Help: "",
}, labels),
LastLevelReadCount: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "lsm",
Name: "last_level_read_count",
Help: "",
}, labels),
NonLastLevelReadBytes: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "lsm",
Name: "non_last_level_read_bytes",
Help: "",
}, labels),
NonLastLevelReadCount: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "lsm",
Name: "non_last_level_read_count",
Help: "",
}, labels),
GetHitL0: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "lsm",
Name: "get_hit_l0",
Help: "number of Get() queries served by L0",
}, labels),
GetHitL1: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "lsm",
Name: "get_hit_l1",
Help: "number of Get() queries served by L1",
}, labels),
GetHitL2AndUp: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: "rocksdb",
Subsystem: "lsm",
Name: "get_hit_l2_and_up",
Help: "number of Get() queries served by L2 and up",
}, labels),
}
}
// report reports metrics to prometheus based on rocksdb props and stats
func (m *Metrics) report(props *properties, stats *stats) {
// Keys
m.NumberKeysWritten.Set(float64(stats.NumberKeysWritten))
m.NumberKeysRead.Set(float64(stats.NumberKeysRead))
m.NumberKeysUpdated.Set(float64(stats.NumberKeysUpdated))
m.EstimateNumKeys.Set(float64(props.EstimateNumKeys))
// Files
m.NumberFileOpens.Set(float64(stats.NumberFileOpens))
m.NumberFileErrors.Set(float64(stats.NumberFileErrors))
// Memory
m.BlockCacheUsage.Set(float64(props.BlockCacheUsage))
m.EstimateTableReadersMem.Set(float64(props.EstimateTableReadersMem))
m.CurSizeAllMemTables.Set(float64(props.CurSizeAllMemTables))
m.BlockCachePinnedUsage.Set(float64(props.BlockCachePinnedUsage))
// Cache
m.BlockCacheMiss.Set(float64(stats.BlockCacheMiss))
m.BlockCacheHit.Set(float64(stats.BlockCacheHit))
m.BlockCacheAdd.Set(float64(stats.BlockCacheAdd))
m.BlockCacheAddFailures.Set(float64(stats.BlockCacheAddFailures))
// Detailed Cache
m.BlockCacheIndexMiss.Set(float64(stats.BlockCacheIndexMiss))
m.BlockCacheIndexHit.Set(float64(stats.BlockCacheIndexHit))
m.BlockCacheIndexBytesInsert.Set(float64(stats.BlockCacheIndexBytesInsert))
m.BlockCacheFilterMiss.Set(float64(stats.BlockCacheFilterMiss))
m.BlockCacheFilterHit.Set(float64(stats.BlockCacheFilterHit))
m.BlockCacheFilterBytesInsert.Set(float64(stats.BlockCacheFilterBytesInsert))
m.BlockCacheDataMiss.Set(float64(stats.BlockCacheDataMiss))
m.BlockCacheDataHit.Set(float64(stats.BlockCacheDataHit))
m.BlockCacheDataBytesInsert.Set(float64(stats.BlockCacheDataBytesInsert))
// Latency
m.DBGetMicrosP50.Set(stats.DBGetMicros.P50)
m.DBGetMicrosP95.Set(stats.DBGetMicros.P95)
m.DBGetMicrosP99.Set(stats.DBGetMicros.P99)
m.DBGetMicrosP100.Set(stats.DBGetMicros.P100)
m.DBGetMicrosCount.Set(stats.DBGetMicros.Count)
m.DBWriteMicrosP50.Set(stats.DBWriteMicros.P50)
m.DBWriteMicrosP95.Set(stats.DBWriteMicros.P95)
m.DBWriteMicrosP99.Set(stats.DBWriteMicros.P99)
m.DBWriteMicrosP100.Set(stats.DBWriteMicros.P100)
m.DBWriteMicrosCount.Set(stats.DBWriteMicros.Count)
// Write Stall
m.StallMicros.Set(float64(stats.StallMicros))
m.DBWriteStallP50.Set(stats.DBWriteStallHistogram.P50)
m.DBWriteStallP95.Set(stats.DBWriteStallHistogram.P95)
m.DBWriteStallP99.Set(stats.DBWriteStallHistogram.P99)
m.DBWriteStallP100.Set(stats.DBWriteStallHistogram.P100)
m.DBWriteStallCount.Set(stats.DBWriteStallHistogram.Count)
m.DBWriteStallSum.Set(stats.DBWriteStallHistogram.Sum)
// Bloom Filter
m.BloomFilterUseful.Set(float64(stats.BloomFilterUseful))
m.BloomFilterFullPositive.Set(float64(stats.BloomFilterFullPositive))
m.BloomFilterFullTruePositive.Set(float64(stats.BloomFilterFullTruePositive))
// LSM Tree Stats
m.LastLevelReadBytes.Set(float64(stats.LastLevelReadBytes))
m.LastLevelReadCount.Set(float64(stats.LastLevelReadCount))
m.NonLastLevelReadBytes.Set(float64(stats.NonLastLevelReadBytes))
m.NonLastLevelReadCount.Set(float64(stats.NonLastLevelReadCount))
m.GetHitL0.Set(float64(stats.GetHitL0))
m.GetHitL1.Set(float64(stats.GetHitL1))
m.GetHitL2AndUp.Set(float64(stats.GetHitL2AndUp))
}

View File

@ -1,18 +0,0 @@
//go:build !rocksdb
// +build !rocksdb
package opendb
import (
"path/filepath"
dbm "github.com/cometbft/cometbft-db"
"github.com/cosmos/cosmos-sdk/server/types"
)
// OpenDB is a copy of default DBOpener function used by ethermint, see for details:
// https://github.com/evmos/ethermint/blob/07cf2bd2b1ce9bdb2e44ec42a39e7239292a14af/server/start.go#L647
func OpenDB(_ types.AppOptions, home string, backendType dbm.BackendType) (dbm.DB, error) {
dataDir := filepath.Join(home, "data")
return dbm.NewDB("application", backendType, dataDir)
}

View File

@ -1,398 +0,0 @@
//go:build rocksdb
// +build rocksdb
// Copyright 2023 Kava Labs, Inc.
// Copyright 2023 Cronos Labs, Inc.
//
// Derived from https://github.com/crypto-org-chain/cronos@496ce7e
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package opendb
import (
"errors"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"time"
dbm "github.com/cometbft/cometbft-db"
"github.com/cosmos/cosmos-sdk/server/types"
"github.com/linxGnu/grocksdb"
"github.com/spf13/cast"
)
var ErrUnexpectedConfiguration = errors.New("unexpected rocksdb configuration, rocksdb should have only one column family named default")
const (
// default tm-db block cache size for RocksDB
defaultBlockCacheSize = 1 << 30
DefaultColumnFamilyName = "default"
enableMetricsOptName = "rocksdb.enable-metrics"
reportMetricsIntervalSecsOptName = "rocksdb.report-metrics-interval-secs"
defaultReportMetricsIntervalSecs = 15
maxOpenFilesDBOptName = "rocksdb.max-open-files"
maxFileOpeningThreadsDBOptName = "rocksdb.max-file-opening-threads"
tableCacheNumshardbitsDBOptName = "rocksdb.table_cache_numshardbits"
allowMMAPWritesDBOptName = "rocksdb.allow_mmap_writes"
allowMMAPReadsDBOptName = "rocksdb.allow_mmap_reads"
useFsyncDBOptName = "rocksdb.use_fsync"
useAdaptiveMutexDBOptName = "rocksdb.use_adaptive_mutex"
bytesPerSyncDBOptName = "rocksdb.bytes_per_sync"
maxBackgroundJobsDBOptName = "rocksdb.max-background-jobs"
writeBufferSizeCFOptName = "rocksdb.write-buffer-size"
numLevelsCFOptName = "rocksdb.num-levels"
maxWriteBufferNumberCFOptName = "rocksdb.max_write_buffer_number"
minWriteBufferNumberToMergeCFOptName = "rocksdb.min_write_buffer_number_to_merge"
maxBytesForLevelBaseCFOptName = "rocksdb.max_bytes_for_level_base"
maxBytesForLevelMultiplierCFOptName = "rocksdb.max_bytes_for_level_multiplier"
targetFileSizeBaseCFOptName = "rocksdb.target_file_size_base"
targetFileSizeMultiplierCFOptName = "rocksdb.target_file_size_multiplier"
level0FileNumCompactionTriggerCFOptName = "rocksdb.level0_file_num_compaction_trigger"
level0SlowdownWritesTriggerCFOptName = "rocksdb.level0_slowdown_writes_trigger"
blockCacheSizeBBTOOptName = "rocksdb.block_cache_size"
bitsPerKeyBBTOOptName = "rocksdb.bits_per_key"
blockSizeBBTOOptName = "rocksdb.block_size"
cacheIndexAndFilterBlocksBBTOOptName = "rocksdb.cache_index_and_filter_blocks"
pinL0FilterAndIndexBlocksInCacheBBTOOptName = "rocksdb.pin_l0_filter_and_index_blocks_in_cache"
formatVersionBBTOOptName = "rocksdb.format_version"
asyncIOReadOptName = "rocksdb.read-async-io"
)
func OpenDB(appOpts types.AppOptions, home string, backendType dbm.BackendType) (dbm.DB, error) {
dataDir := filepath.Join(home, "data")
if backendType == dbm.RocksDBBackend {
return openRocksdb(dataDir, appOpts)
}
return dbm.NewDB("application", backendType, dataDir)
}
// openRocksdb loads existing options, overrides some of them with appOpts and opens database
// option will be overridden only in case if it explicitly specified in appOpts
func openRocksdb(dir string, appOpts types.AppOptions) (dbm.DB, error) {
optionsPath := filepath.Join(dir, "application.db")
dbOpts, cfOpts, err := LoadLatestOptions(optionsPath)
if err != nil {
return nil, err
}
// customize rocksdb options
bbtoOpts := bbtoFromAppOpts(appOpts)
dbOpts.SetBlockBasedTableFactory(bbtoOpts)
cfOpts.SetBlockBasedTableFactory(bbtoOpts)
dbOpts = overrideDBOpts(dbOpts, appOpts)
cfOpts = overrideCFOpts(cfOpts, appOpts)
readOpts := readOptsFromAppOpts(appOpts)
enableMetrics := cast.ToBool(appOpts.Get(enableMetricsOptName))
reportMetricsIntervalSecs := cast.ToInt64(appOpts.Get(reportMetricsIntervalSecsOptName))
if reportMetricsIntervalSecs == 0 {
reportMetricsIntervalSecs = defaultReportMetricsIntervalSecs
}
return newRocksDBWithOptions("application", dir, dbOpts, cfOpts, readOpts, enableMetrics, reportMetricsIntervalSecs)
}
// LoadLatestOptions loads and returns database and column family options
// if options file not found, it means database isn't created yet, in such case default tm-db options will be returned
// if database exists it should have only one column family named default
func LoadLatestOptions(dir string) (*grocksdb.Options, *grocksdb.Options, error) {
latestOpts, err := grocksdb.LoadLatestOptions(dir, grocksdb.NewDefaultEnv(), true, grocksdb.NewLRUCache(defaultBlockCacheSize))
if err != nil && strings.HasPrefix(err.Error(), "NotFound: ") {
return newDefaultOptions(), newDefaultOptions(), nil
}
if err != nil {
return nil, nil, err
}
cfNames := latestOpts.ColumnFamilyNames()
cfOpts := latestOpts.ColumnFamilyOpts()
// db should have only one column family named default
ok := len(cfNames) == 1 && cfNames[0] == DefaultColumnFamilyName
if !ok {
return nil, nil, ErrUnexpectedConfiguration
}
// return db and cf opts
return latestOpts.Options(), &cfOpts[0], nil
}
// overrideDBOpts merges dbOpts and appOpts, appOpts takes precedence
func overrideDBOpts(dbOpts *grocksdb.Options, appOpts types.AppOptions) *grocksdb.Options {
maxOpenFiles := appOpts.Get(maxOpenFilesDBOptName)
if maxOpenFiles != nil {
dbOpts.SetMaxOpenFiles(cast.ToInt(maxOpenFiles))
}
maxFileOpeningThreads := appOpts.Get(maxFileOpeningThreadsDBOptName)
if maxFileOpeningThreads != nil {
dbOpts.SetMaxFileOpeningThreads(cast.ToInt(maxFileOpeningThreads))
}
tableCacheNumshardbits := appOpts.Get(tableCacheNumshardbitsDBOptName)
if tableCacheNumshardbits != nil {
dbOpts.SetTableCacheNumshardbits(cast.ToInt(tableCacheNumshardbits))
}
allowMMAPWrites := appOpts.Get(allowMMAPWritesDBOptName)
if allowMMAPWrites != nil {
dbOpts.SetAllowMmapWrites(cast.ToBool(allowMMAPWrites))
}
allowMMAPReads := appOpts.Get(allowMMAPReadsDBOptName)
if allowMMAPReads != nil {
dbOpts.SetAllowMmapReads(cast.ToBool(allowMMAPReads))
}
useFsync := appOpts.Get(useFsyncDBOptName)
if useFsync != nil {
dbOpts.SetUseFsync(cast.ToBool(useFsync))
}
useAdaptiveMutex := appOpts.Get(useAdaptiveMutexDBOptName)
if useAdaptiveMutex != nil {
dbOpts.SetUseAdaptiveMutex(cast.ToBool(useAdaptiveMutex))
}
bytesPerSync := appOpts.Get(bytesPerSyncDBOptName)
if bytesPerSync != nil {
dbOpts.SetBytesPerSync(cast.ToUint64(bytesPerSync))
}
maxBackgroundJobs := appOpts.Get(maxBackgroundJobsDBOptName)
if maxBackgroundJobs != nil {
dbOpts.SetMaxBackgroundJobs(cast.ToInt(maxBackgroundJobs))
}
return dbOpts
}
// overrideCFOpts merges cfOpts and appOpts, appOpts takes precedence
func overrideCFOpts(cfOpts *grocksdb.Options, appOpts types.AppOptions) *grocksdb.Options {
writeBufferSize := appOpts.Get(writeBufferSizeCFOptName)
if writeBufferSize != nil {
cfOpts.SetWriteBufferSize(cast.ToUint64(writeBufferSize))
}
numLevels := appOpts.Get(numLevelsCFOptName)
if numLevels != nil {
cfOpts.SetNumLevels(cast.ToInt(numLevels))
}
maxWriteBufferNumber := appOpts.Get(maxWriteBufferNumberCFOptName)
if maxWriteBufferNumber != nil {
cfOpts.SetMaxWriteBufferNumber(cast.ToInt(maxWriteBufferNumber))
}
minWriteBufferNumberToMerge := appOpts.Get(minWriteBufferNumberToMergeCFOptName)
if minWriteBufferNumberToMerge != nil {
cfOpts.SetMinWriteBufferNumberToMerge(cast.ToInt(minWriteBufferNumberToMerge))
}
maxBytesForLevelBase := appOpts.Get(maxBytesForLevelBaseCFOptName)
if maxBytesForLevelBase != nil {
cfOpts.SetMaxBytesForLevelBase(cast.ToUint64(maxBytesForLevelBase))
}
maxBytesForLevelMultiplier := appOpts.Get(maxBytesForLevelMultiplierCFOptName)
if maxBytesForLevelMultiplier != nil {
cfOpts.SetMaxBytesForLevelMultiplier(cast.ToFloat64(maxBytesForLevelMultiplier))
}
targetFileSizeBase := appOpts.Get(targetFileSizeBaseCFOptName)
if targetFileSizeBase != nil {
cfOpts.SetTargetFileSizeBase(cast.ToUint64(targetFileSizeBase))
}
targetFileSizeMultiplier := appOpts.Get(targetFileSizeMultiplierCFOptName)
if targetFileSizeMultiplier != nil {
cfOpts.SetTargetFileSizeMultiplier(cast.ToInt(targetFileSizeMultiplier))
}
level0FileNumCompactionTrigger := appOpts.Get(level0FileNumCompactionTriggerCFOptName)
if level0FileNumCompactionTrigger != nil {
cfOpts.SetLevel0FileNumCompactionTrigger(cast.ToInt(level0FileNumCompactionTrigger))
}
level0SlowdownWritesTrigger := appOpts.Get(level0SlowdownWritesTriggerCFOptName)
if level0SlowdownWritesTrigger != nil {
cfOpts.SetLevel0SlowdownWritesTrigger(cast.ToInt(level0SlowdownWritesTrigger))
}
return cfOpts
}
func readOptsFromAppOpts(appOpts types.AppOptions) *grocksdb.ReadOptions {
ro := grocksdb.NewDefaultReadOptions()
asyncIO := appOpts.Get(asyncIOReadOptName)
if asyncIO != nil {
ro.SetAsyncIO(cast.ToBool(asyncIO))
}
return ro
}
func bbtoFromAppOpts(appOpts types.AppOptions) *grocksdb.BlockBasedTableOptions {
bbto := defaultBBTO()
blockCacheSize := appOpts.Get(blockCacheSizeBBTOOptName)
if blockCacheSize != nil {
cache := grocksdb.NewLRUCache(cast.ToUint64(blockCacheSize))
bbto.SetBlockCache(cache)
}
bitsPerKey := appOpts.Get(bitsPerKeyBBTOOptName)
if bitsPerKey != nil {
filter := grocksdb.NewBloomFilter(cast.ToFloat64(bitsPerKey))
bbto.SetFilterPolicy(filter)
}
blockSize := appOpts.Get(blockSizeBBTOOptName)
if blockSize != nil {
bbto.SetBlockSize(cast.ToInt(blockSize))
}
cacheIndexAndFilterBlocks := appOpts.Get(cacheIndexAndFilterBlocksBBTOOptName)
if cacheIndexAndFilterBlocks != nil {
bbto.SetCacheIndexAndFilterBlocks(cast.ToBool(cacheIndexAndFilterBlocks))
}
pinL0FilterAndIndexBlocksInCache := appOpts.Get(pinL0FilterAndIndexBlocksInCacheBBTOOptName)
if pinL0FilterAndIndexBlocksInCache != nil {
bbto.SetPinL0FilterAndIndexBlocksInCache(cast.ToBool(pinL0FilterAndIndexBlocksInCache))
}
formatVersion := appOpts.Get(formatVersionBBTOOptName)
if formatVersion != nil {
bbto.SetFormatVersion(cast.ToInt(formatVersion))
}
return bbto
}
// newRocksDBWithOptions opens rocksdb with provided database and column family options
// newRocksDBWithOptions expects that db has only one column family named default
func newRocksDBWithOptions(
name string,
dir string,
dbOpts *grocksdb.Options,
cfOpts *grocksdb.Options,
readOpts *grocksdb.ReadOptions,
enableMetrics bool,
reportMetricsIntervalSecs int64,
) (*dbm.RocksDB, error) {
dbPath := filepath.Join(dir, name+".db")
// Ensure path exists
if err := os.MkdirAll(dbPath, 0755); err != nil {
return nil, fmt.Errorf("failed to create db path: %w", err)
}
// EnableStatistics adds overhead so shouldn't be enabled in production
if enableMetrics {
dbOpts.EnableStatistics()
}
db, _, err := grocksdb.OpenDbColumnFamilies(dbOpts, dbPath, []string{DefaultColumnFamilyName}, []*grocksdb.Options{cfOpts})
if err != nil {
return nil, err
}
if enableMetrics {
registerMetrics()
go reportMetrics(db, time.Second*time.Duration(reportMetricsIntervalSecs))
}
wo := grocksdb.NewDefaultWriteOptions()
woSync := grocksdb.NewDefaultWriteOptions()
woSync.SetSync(true)
return dbm.NewRocksDBWithRawDB(db, readOpts, wo, woSync), nil
}
// newDefaultOptions returns default tm-db options for RocksDB, see for details:
// https://github.com/Kava-Labs/tm-db/blob/94ff76d31724965f8883cddebabe91e0d01bc03f/rocksdb.go#L30
func newDefaultOptions() *grocksdb.Options {
// default rocksdb option, good enough for most cases, including heavy workloads.
// 1GB table cache, 512MB write buffer(may use 50% more on heavy workloads).
// compression: snappy as default, need to -lsnappy to enable.
bbto := defaultBBTO()
opts := grocksdb.NewDefaultOptions()
opts.SetBlockBasedTableFactory(bbto)
// SetMaxOpenFiles to 4096 seems to provide a reliable performance boost
opts.SetMaxOpenFiles(4096)
opts.SetCreateIfMissing(true)
opts.IncreaseParallelism(runtime.NumCPU())
// 1.5GB maximum memory use for writebuffer.
opts.OptimizeLevelStyleCompaction(512 * 1024 * 1024)
return opts
}
// defaultBBTO returns default tm-db bbto options for RocksDB, see for details:
// https://github.com/Kava-Labs/tm-db/blob/94ff76d31724965f8883cddebabe91e0d01bc03f/rocksdb.go#L30
func defaultBBTO() *grocksdb.BlockBasedTableOptions {
bbto := grocksdb.NewDefaultBlockBasedTableOptions()
bbto.SetBlockCache(grocksdb.NewLRUCache(defaultBlockCacheSize))
bbto.SetFilterPolicy(grocksdb.NewBloomFilter(10))
return bbto
}
// reportMetrics periodically requests stats from rocksdb and reports to prometheus
// NOTE: should be launched as a goroutine
func reportMetrics(db *grocksdb.DB, interval time.Duration) {
ticker := time.NewTicker(interval)
for {
select {
case <-ticker.C:
props, stats, err := getPropsAndStats(db)
if err != nil {
continue
}
rocksdbMetrics.report(props, stats)
}
}
}
// getPropsAndStats gets statistics from rocksdb
func getPropsAndStats(db *grocksdb.DB) (*properties, *stats, error) {
propsLoader := newPropsLoader(db)
props, err := propsLoader.load()
if err != nil {
return nil, nil, err
}
statMap, err := parseSerializedStats(props.OptionsStatistics)
if err != nil {
return nil, nil, err
}
statLoader := newStatLoader(statMap)
stats, err := statLoader.load()
if err != nil {
return nil, nil, err
}
return props, stats, nil
}

View File

@ -1,384 +0,0 @@
//go:build rocksdb
// +build rocksdb
package opendb
import (
"os"
"path/filepath"
"testing"
"github.com/linxGnu/grocksdb"
"github.com/stretchr/testify/require"
)
type mockAppOptions struct {
opts map[string]interface{}
}
func newMockAppOptions(opts map[string]interface{}) *mockAppOptions {
return &mockAppOptions{
opts: opts,
}
}
func (m *mockAppOptions) Get(key string) interface{} {
return m.opts[key]
}
func TestOpenRocksdb(t *testing.T) {
t.Run("db already exists", func(t *testing.T) {
defaultOpts := newDefaultOptions()
for _, tc := range []struct {
desc string
mockAppOptions *mockAppOptions
maxOpenFiles int
maxFileOpeningThreads int
writeBufferSize uint64
numLevels int
}{
{
desc: "default options",
mockAppOptions: newMockAppOptions(map[string]interface{}{}),
maxOpenFiles: defaultOpts.GetMaxOpenFiles(),
maxFileOpeningThreads: defaultOpts.GetMaxFileOpeningThreads(),
writeBufferSize: defaultOpts.GetWriteBufferSize(),
numLevels: defaultOpts.GetNumLevels(),
},
{
desc: "change 2 options",
mockAppOptions: newMockAppOptions(map[string]interface{}{
maxOpenFilesDBOptName: 999,
writeBufferSizeCFOptName: 999_999,
}),
maxOpenFiles: 999,
maxFileOpeningThreads: defaultOpts.GetMaxFileOpeningThreads(),
writeBufferSize: 999_999,
numLevels: defaultOpts.GetNumLevels(),
},
{
desc: "change 4 options",
mockAppOptions: newMockAppOptions(map[string]interface{}{
maxOpenFilesDBOptName: 999,
maxFileOpeningThreadsDBOptName: 9,
writeBufferSizeCFOptName: 999_999,
numLevelsCFOptName: 9,
}),
maxOpenFiles: 999,
maxFileOpeningThreads: 9,
writeBufferSize: 999_999,
numLevels: 9,
},
} {
t.Run(tc.desc, func(t *testing.T) {
dir, err := os.MkdirTemp("", "rocksdb")
require.NoError(t, err)
defer func() {
err := os.RemoveAll(dir)
require.NoError(t, err)
}()
db, err := openRocksdb(dir, tc.mockAppOptions)
require.NoError(t, err)
require.NoError(t, db.Close())
dbOpts, cfOpts, err := LoadLatestOptions(filepath.Join(dir, "application.db"))
require.NoError(t, err)
require.Equal(t, tc.maxOpenFiles, dbOpts.GetMaxOpenFiles())
require.Equal(t, tc.maxFileOpeningThreads, dbOpts.GetMaxFileOpeningThreads())
require.Equal(t, tc.writeBufferSize, cfOpts.GetWriteBufferSize())
require.Equal(t, tc.numLevels, cfOpts.GetNumLevels())
})
}
})
t.Run("db doesn't exist yet", func(t *testing.T) {
defaultOpts := newDefaultOptions()
dir, err := os.MkdirTemp("", "rocksdb")
require.NoError(t, err)
defer func() {
err := os.RemoveAll(dir)
require.NoError(t, err)
}()
mockAppOpts := newMockAppOptions(map[string]interface{}{})
db, err := openRocksdb(dir, mockAppOpts)
require.NoError(t, err)
require.NoError(t, db.Close())
dbOpts, cfOpts, err := LoadLatestOptions(filepath.Join(dir, "application.db"))
require.NoError(t, err)
require.Equal(t, defaultOpts.GetMaxOpenFiles(), dbOpts.GetMaxOpenFiles())
require.Equal(t, defaultOpts.GetMaxFileOpeningThreads(), dbOpts.GetMaxFileOpeningThreads())
require.Equal(t, defaultOpts.GetWriteBufferSize(), cfOpts.GetWriteBufferSize())
require.Equal(t, defaultOpts.GetNumLevels(), cfOpts.GetNumLevels())
})
}
func TestLoadLatestOptions(t *testing.T) {
t.Run("db already exists", func(t *testing.T) {
defaultOpts := newDefaultOptions()
const testCasesNum = 3
dbOptsList := make([]*grocksdb.Options, testCasesNum)
cfOptsList := make([]*grocksdb.Options, testCasesNum)
dbOptsList[0] = newDefaultOptions()
cfOptsList[0] = newDefaultOptions()
dbOptsList[1] = newDefaultOptions()
dbOptsList[1].SetMaxOpenFiles(999)
cfOptsList[1] = newDefaultOptions()
cfOptsList[1].SetWriteBufferSize(999_999)
dbOptsList[2] = newDefaultOptions()
dbOptsList[2].SetMaxOpenFiles(999)
dbOptsList[2].SetMaxFileOpeningThreads(9)
cfOptsList[2] = newDefaultOptions()
cfOptsList[2].SetWriteBufferSize(999_999)
cfOptsList[2].SetNumLevels(9)
for _, tc := range []struct {
desc string
dbOpts *grocksdb.Options
cfOpts *grocksdb.Options
maxOpenFiles int
maxFileOpeningThreads int
writeBufferSize uint64
numLevels int
}{
{
desc: "default options",
dbOpts: dbOptsList[0],
cfOpts: cfOptsList[0],
maxOpenFiles: defaultOpts.GetMaxOpenFiles(),
maxFileOpeningThreads: defaultOpts.GetMaxFileOpeningThreads(),
writeBufferSize: defaultOpts.GetWriteBufferSize(),
numLevels: defaultOpts.GetNumLevels(),
},
{
desc: "change 2 options",
dbOpts: dbOptsList[1],
cfOpts: cfOptsList[1],
maxOpenFiles: 999,
maxFileOpeningThreads: defaultOpts.GetMaxFileOpeningThreads(),
writeBufferSize: 999_999,
numLevels: defaultOpts.GetNumLevels(),
},
{
desc: "change 4 options",
dbOpts: dbOptsList[2],
cfOpts: cfOptsList[2],
maxOpenFiles: 999,
maxFileOpeningThreads: 9,
writeBufferSize: 999_999,
numLevels: 9,
},
} {
t.Run(tc.desc, func(t *testing.T) {
name := "application"
dir, err := os.MkdirTemp("", "rocksdb")
require.NoError(t, err)
defer func() {
err := os.RemoveAll(dir)
require.NoError(t, err)
}()
db, err := newRocksDBWithOptions(name, dir, tc.dbOpts, tc.cfOpts, grocksdb.NewDefaultReadOptions(), true, defaultReportMetricsIntervalSecs)
require.NoError(t, err)
require.NoError(t, db.Close())
dbOpts, cfOpts, err := LoadLatestOptions(filepath.Join(dir, "application.db"))
require.NoError(t, err)
require.Equal(t, tc.maxOpenFiles, dbOpts.GetMaxOpenFiles())
require.Equal(t, tc.maxFileOpeningThreads, dbOpts.GetMaxFileOpeningThreads())
require.Equal(t, tc.writeBufferSize, cfOpts.GetWriteBufferSize())
require.Equal(t, tc.numLevels, cfOpts.GetNumLevels())
})
}
})
t.Run("db doesn't exist yet", func(t *testing.T) {
defaultOpts := newDefaultOptions()
dir, err := os.MkdirTemp("", "rocksdb")
require.NoError(t, err)
defer func() {
err := os.RemoveAll(dir)
require.NoError(t, err)
}()
dbOpts, cfOpts, err := LoadLatestOptions(filepath.Join(dir, "application.db"))
require.NoError(t, err)
require.Equal(t, defaultOpts.GetMaxOpenFiles(), dbOpts.GetMaxOpenFiles())
require.Equal(t, defaultOpts.GetMaxFileOpeningThreads(), dbOpts.GetMaxFileOpeningThreads())
require.Equal(t, defaultOpts.GetWriteBufferSize(), cfOpts.GetWriteBufferSize())
require.Equal(t, defaultOpts.GetNumLevels(), cfOpts.GetNumLevels())
})
}
func TestOverrideDBOpts(t *testing.T) {
defaultOpts := newDefaultOptions()
for _, tc := range []struct {
desc string
mockAppOptions *mockAppOptions
maxOpenFiles int
maxFileOpeningThreads int
}{
{
desc: "override nothing",
mockAppOptions: newMockAppOptions(map[string]interface{}{}),
maxOpenFiles: defaultOpts.GetMaxOpenFiles(),
maxFileOpeningThreads: defaultOpts.GetMaxFileOpeningThreads(),
},
{
desc: "override max-open-files",
mockAppOptions: newMockAppOptions(map[string]interface{}{
maxOpenFilesDBOptName: 999,
}),
maxOpenFiles: 999,
maxFileOpeningThreads: defaultOpts.GetMaxFileOpeningThreads(),
},
{
desc: "override max-file-opening-threads",
mockAppOptions: newMockAppOptions(map[string]interface{}{
maxFileOpeningThreadsDBOptName: 9,
}),
maxOpenFiles: defaultOpts.GetMaxOpenFiles(),
maxFileOpeningThreads: 9,
},
{
desc: "override max-open-files and max-file-opening-threads",
mockAppOptions: newMockAppOptions(map[string]interface{}{
maxOpenFilesDBOptName: 999,
maxFileOpeningThreadsDBOptName: 9,
}),
maxOpenFiles: 999,
maxFileOpeningThreads: 9,
},
} {
t.Run(tc.desc, func(t *testing.T) {
dbOpts := newDefaultOptions()
dbOpts = overrideDBOpts(dbOpts, tc.mockAppOptions)
require.Equal(t, tc.maxOpenFiles, dbOpts.GetMaxOpenFiles())
require.Equal(t, tc.maxFileOpeningThreads, dbOpts.GetMaxFileOpeningThreads())
})
}
}
func TestOverrideCFOpts(t *testing.T) {
defaultOpts := newDefaultOptions()
for _, tc := range []struct {
desc string
mockAppOptions *mockAppOptions
writeBufferSize uint64
numLevels int
}{
{
desc: "override nothing",
mockAppOptions: newMockAppOptions(map[string]interface{}{}),
writeBufferSize: defaultOpts.GetWriteBufferSize(),
numLevels: defaultOpts.GetNumLevels(),
},
{
desc: "override write-buffer-size",
mockAppOptions: newMockAppOptions(map[string]interface{}{
writeBufferSizeCFOptName: 999_999,
}),
writeBufferSize: 999_999,
numLevels: defaultOpts.GetNumLevels(),
},
{
desc: "override num-levels",
mockAppOptions: newMockAppOptions(map[string]interface{}{
numLevelsCFOptName: 9,
}),
writeBufferSize: defaultOpts.GetWriteBufferSize(),
numLevels: 9,
},
{
desc: "override write-buffer-size and num-levels",
mockAppOptions: newMockAppOptions(map[string]interface{}{
writeBufferSizeCFOptName: 999_999,
numLevelsCFOptName: 9,
}),
writeBufferSize: 999_999,
numLevels: 9,
},
} {
t.Run(tc.desc, func(t *testing.T) {
cfOpts := newDefaultOptions()
cfOpts = overrideCFOpts(cfOpts, tc.mockAppOptions)
require.Equal(t, tc.writeBufferSize, cfOpts.GetWriteBufferSize())
require.Equal(t, tc.numLevels, cfOpts.GetNumLevels())
})
}
}
func TestReadOptsFromAppOpts(t *testing.T) {
for _, tc := range []struct {
desc string
mockAppOptions *mockAppOptions
asyncIO bool
}{
{
desc: "default options",
mockAppOptions: newMockAppOptions(map[string]interface{}{}),
asyncIO: false,
},
{
desc: "set asyncIO option to true",
mockAppOptions: newMockAppOptions(map[string]interface{}{
asyncIOReadOptName: true,
}),
asyncIO: true,
},
} {
t.Run(tc.desc, func(t *testing.T) {
readOpts := readOptsFromAppOpts(tc.mockAppOptions)
require.Equal(t, tc.asyncIO, readOpts.IsAsyncIO())
})
}
}
func TestNewRocksDBWithOptions(t *testing.T) {
defaultOpts := newDefaultOptions()
name := "application"
dir, err := os.MkdirTemp("", "rocksdb")
require.NoError(t, err)
defer func() {
err := os.RemoveAll(dir)
require.NoError(t, err)
}()
dbOpts := newDefaultOptions()
dbOpts.SetMaxOpenFiles(999)
cfOpts := newDefaultOptions()
cfOpts.SetWriteBufferSize(999_999)
db, err := newRocksDBWithOptions(name, dir, dbOpts, cfOpts, grocksdb.NewDefaultReadOptions(), true, defaultReportMetricsIntervalSecs)
require.NoError(t, err)
require.NoError(t, db.Close())
dbOpts, cfOpts, err = LoadLatestOptions(filepath.Join(dir, "application.db"))
require.NoError(t, err)
require.Equal(t, 999, dbOpts.GetMaxOpenFiles())
require.Equal(t, defaultOpts.GetMaxFileOpeningThreads(), dbOpts.GetMaxFileOpeningThreads())
require.Equal(t, uint64(999_999), cfOpts.GetWriteBufferSize())
require.Equal(t, defaultOpts.GetNumLevels(), dbOpts.GetNumLevels())
}
func TestNewDefaultOptions(t *testing.T) {
defaultOpts := newDefaultOptions()
maxOpenFiles := defaultOpts.GetMaxOpenFiles()
require.Equal(t, 4096, maxOpenFiles)
}

View File

@ -1,87 +0,0 @@
//go:build rocksdb
// +build rocksdb
package opendb
import (
"fmt"
"strings"
"errors"
)
type propsGetter interface {
GetProperty(propName string) (value string)
GetIntProperty(propName string) (value uint64, success bool)
}
type propsLoader struct {
db propsGetter
errorMsgs []string
}
func newPropsLoader(db propsGetter) *propsLoader {
return &propsLoader{
db: db,
errorMsgs: make([]string, 0),
}
}
func (l *propsLoader) load() (*properties, error) {
props := &properties{
BaseLevel: l.getIntProperty("rocksdb.base-level"),
BlockCacheCapacity: l.getIntProperty("rocksdb.block-cache-capacity"),
BlockCachePinnedUsage: l.getIntProperty("rocksdb.block-cache-pinned-usage"),
BlockCacheUsage: l.getIntProperty("rocksdb.block-cache-usage"),
CurSizeActiveMemTable: l.getIntProperty("rocksdb.cur-size-active-mem-table"),
CurSizeAllMemTables: l.getIntProperty("rocksdb.cur-size-all-mem-tables"),
EstimateLiveDataSize: l.getIntProperty("rocksdb.estimate-live-data-size"),
EstimateNumKeys: l.getIntProperty("rocksdb.estimate-num-keys"),
EstimateTableReadersMem: l.getIntProperty("rocksdb.estimate-table-readers-mem"),
LiveSSTFilesSize: l.getIntProperty("rocksdb.live-sst-files-size"),
SizeAllMemTables: l.getIntProperty("rocksdb.size-all-mem-tables"),
OptionsStatistics: l.getProperty("rocksdb.options-statistics"),
}
if len(l.errorMsgs) != 0 {
errorMsg := strings.Join(l.errorMsgs, ";")
return nil, errors.New(errorMsg)
}
return props, nil
}
func (l *propsLoader) getProperty(propName string) string {
value := l.db.GetProperty(propName)
if value == "" {
l.errorMsgs = append(l.errorMsgs, fmt.Sprintf("property %v is empty", propName))
return ""
}
return value
}
func (l *propsLoader) getIntProperty(propName string) uint64 {
value, ok := l.db.GetIntProperty(propName)
if !ok {
l.errorMsgs = append(l.errorMsgs, fmt.Sprintf("can't get %v int property", propName))
return 0
}
return value
}
type properties struct {
BaseLevel uint64
BlockCacheCapacity uint64
BlockCachePinnedUsage uint64
BlockCacheUsage uint64
CurSizeActiveMemTable uint64
CurSizeAllMemTables uint64
EstimateLiveDataSize uint64
EstimateNumKeys uint64
EstimateTableReadersMem uint64
LiveSSTFilesSize uint64
SizeAllMemTables uint64
OptionsStatistics string
}

View File

@ -1,112 +0,0 @@
//go:build rocksdb
// +build rocksdb
package opendb
import (
"testing"
"github.com/stretchr/testify/require"
)
type mockPropsGetter struct {
props map[string]string
intProps map[string]uint64
}
func newMockPropsGetter(
props map[string]string,
intProps map[string]uint64,
) *mockPropsGetter {
return &mockPropsGetter{
props: props,
intProps: intProps,
}
}
func (m *mockPropsGetter) GetProperty(propName string) string {
return m.props[propName]
}
func (m *mockPropsGetter) GetIntProperty(propName string) (uint64, bool) {
prop, ok := m.intProps[propName]
return prop, ok
}
func TestPropsLoader(t *testing.T) {
defaultProps := map[string]string{
"rocksdb.options-statistics": "1",
}
defaultIntProps := map[string]uint64{
"rocksdb.base-level": 1,
"rocksdb.block-cache-capacity": 2,
"rocksdb.block-cache-pinned-usage": 3,
"rocksdb.block-cache-usage": 4,
"rocksdb.cur-size-active-mem-table": 5,
"rocksdb.cur-size-all-mem-tables": 6,
"rocksdb.estimate-live-data-size": 7,
"rocksdb.estimate-num-keys": 8,
"rocksdb.estimate-table-readers-mem": 9,
"rocksdb.live-sst-files-size": 10,
"rocksdb.size-all-mem-tables": 11,
}
missingProps := make(map[string]string)
missingIntProps := make(map[string]uint64)
defaultExpectedProps := properties{
BaseLevel: 1,
BlockCacheCapacity: 2,
BlockCachePinnedUsage: 3,
BlockCacheUsage: 4,
CurSizeActiveMemTable: 5,
CurSizeAllMemTables: 6,
EstimateLiveDataSize: 7,
EstimateNumKeys: 8,
EstimateTableReadersMem: 9,
LiveSSTFilesSize: 10,
SizeAllMemTables: 11,
OptionsStatistics: "1",
}
for _, tc := range []struct {
desc string
props map[string]string
intProps map[string]uint64
expectedProps *properties
success bool
}{
{
desc: "success case",
props: defaultProps,
intProps: defaultIntProps,
expectedProps: &defaultExpectedProps,
success: true,
},
{
desc: "missing props",
props: missingProps,
intProps: defaultIntProps,
expectedProps: nil,
success: false,
},
{
desc: "missing integer props",
props: defaultProps,
intProps: missingIntProps,
expectedProps: nil,
success: false,
},
} {
t.Run(tc.desc, func(t *testing.T) {
mockPropsGetter := newMockPropsGetter(tc.props, tc.intProps)
propsLoader := newPropsLoader(mockPropsGetter)
actualProps, err := propsLoader.load()
if tc.success {
require.NoError(t, err)
} else {
require.Error(t, err)
}
require.Equal(t, tc.expectedProps, actualProps)
})
}
}

View File

@ -1,111 +0,0 @@
//go:build rocksdb
// +build rocksdb
package opendb
import (
"fmt"
"strings"
"errors"
)
// stat represents one line from rocksdb statistics data, stat may have one or more properties
// examples:
// - rocksdb.block.cache.miss COUNT : 5
// - rocksdb.compaction.times.micros P50 : 21112 P95 : 21112 P99 : 21112 P100 : 21112 COUNT : 1 SUM : 21112
// `rocksdb.compaction.times.micros` is name of stat, P50, COUNT, SUM, etc... are props of stat
type stat struct {
name string
props map[string]string
}
// parseSerializedStats parses serialisedStats into map of stat objects
// example of serializedStats:
// rocksdb.block.cache.miss COUNT : 5
// rocksdb.compaction.times.micros P50 : 21112 P95 : 21112 P99 : 21112 P100 : 21112 COUNT : 1 SUM : 21112
func parseSerializedStats(serializedStats string) (map[string]*stat, error) {
stats := make(map[string]*stat, 0)
serializedStatList := strings.Split(serializedStats, "\n")
if len(serializedStatList) == 0 {
return nil, errors.New("serializedStats is empty")
}
serializedStatList = serializedStatList[:len(serializedStatList)-1]
// iterate over stats line by line
for _, serializedStat := range serializedStatList {
stat, err := parseSerializedStat(serializedStat)
if err != nil {
return nil, err
}
stats[stat.name] = stat
}
return stats, nil
}
// parseSerializedStat parses serialisedStat into stat object
// example of serializedStat:
// rocksdb.block.cache.miss COUNT : 5
func parseSerializedStat(serializedStat string) (*stat, error) {
tokens := strings.Split(serializedStat, " ")
tokensNum := len(tokens)
if err := validateTokens(tokens); err != nil {
return nil, fmt.Errorf("tokens are invalid: %v", err)
}
props := make(map[string]string)
for idx := 1; idx < tokensNum; idx += 3 {
// never should happen, but double check to avoid unexpected panic
if idx+2 >= tokensNum {
break
}
key := tokens[idx]
sep := tokens[idx+1]
value := tokens[idx+2]
if err := validateStatProperty(key, value, sep); err != nil {
return nil, fmt.Errorf("invalid stat property: %v", err)
}
props[key] = value
}
return &stat{
name: tokens[0],
props: props,
}, nil
}
// validateTokens validates that tokens contains name + N triples (key, sep, value)
func validateTokens(tokens []string) error {
tokensNum := len(tokens)
if tokensNum < 4 {
return fmt.Errorf("invalid number of tokens: %v, tokens: %v", tokensNum, tokens)
}
if (tokensNum-1)%3 != 0 {
return fmt.Errorf("invalid number of tokens: %v, tokens: %v", tokensNum, tokens)
}
if tokens[0] == "" {
return fmt.Errorf("stat name shouldn't be empty")
}
return nil
}
// validateStatProperty validates that key and value are divided by separator and aren't empty
func validateStatProperty(key, value, sep string) error {
if key == "" {
return fmt.Errorf("key shouldn't be empty")
}
if sep != ":" {
return fmt.Errorf("separator should be :")
}
if value == "" {
return fmt.Errorf("value shouldn't be empty")
}
return nil
}

View File

@ -1,208 +0,0 @@
//go:build rocksdb
// +build rocksdb
package opendb
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestParseSerializedStats(t *testing.T) {
defaultSerializedStats := `rocksdb.block.cache.miss COUNT : 1
rocksdb.block.cache.hit COUNT : 2
rocksdb.block.cache.add COUNT : 3
rocksdb.block.cache.add.failures COUNT : 4
rocksdb.compaction.times.micros P50 : 1 P95 : 2 P99 : 3 P100 : 4 COUNT : 5 SUM : 6
rocksdb.compaction.times.cpu_micros P50 : 7 P95 : 8 P99 : 9 P100 : 10 COUNT : 11 SUM : 12
`
defaultExpectedStatMap := map[string]*stat{
"rocksdb.block.cache.miss": {
name: "rocksdb.block.cache.miss",
props: map[string]string{
"COUNT": "1",
},
},
"rocksdb.block.cache.hit": {
name: "rocksdb.block.cache.hit",
props: map[string]string{
"COUNT": "2",
},
},
"rocksdb.block.cache.add": {
name: "rocksdb.block.cache.add",
props: map[string]string{
"COUNT": "3",
},
},
"rocksdb.block.cache.add.failures": {
name: "rocksdb.block.cache.add.failures",
props: map[string]string{
"COUNT": "4",
},
},
"rocksdb.compaction.times.micros": {
name: "rocksdb.compaction.times.micros",
props: map[string]string{
"P50": "1",
"P95": "2",
"P99": "3",
"P100": "4",
"COUNT": "5",
"SUM": "6",
},
},
"rocksdb.compaction.times.cpu_micros": {
name: "rocksdb.compaction.times.cpu_micros",
props: map[string]string{
"P50": "7",
"P95": "8",
"P99": "9",
"P100": "10",
"COUNT": "11",
"SUM": "12",
},
},
}
for _, tc := range []struct {
desc string
serializedStats string
expectedStatMap map[string]*stat
errMsg string
}{
{
desc: "success case",
serializedStats: defaultSerializedStats,
expectedStatMap: defaultExpectedStatMap,
errMsg: "",
},
{
desc: "missing value #1",
serializedStats: `rocksdb.block.cache.miss COUNT :
`,
expectedStatMap: nil,
errMsg: "invalid number of tokens",
},
{
desc: "missing value #2",
serializedStats: `rocksdb.compaction.times.micros P50 : 1 P95 :
`,
expectedStatMap: nil,
errMsg: "invalid number of tokens",
},
{
desc: "missing stat name",
serializedStats: ` COUNT : 1
`,
expectedStatMap: nil,
errMsg: "stat name shouldn't be empty",
},
{
desc: "empty stat",
serializedStats: ``,
expectedStatMap: make(map[string]*stat),
errMsg: "",
},
} {
t.Run(tc.desc, func(t *testing.T) {
actualStatMap, err := parseSerializedStats(tc.serializedStats)
if tc.errMsg == "" {
require.NoError(t, err)
} else {
require.Error(t, err)
require.Contains(t, err.Error(), tc.errMsg)
}
require.Equal(t, tc.expectedStatMap, actualStatMap)
})
}
}
func TestValidateTokens(t *testing.T) {
for _, tc := range []struct {
desc string
tokens []string
errMsg string
}{
{
desc: "success case",
tokens: []string{"name", "key", ":", "value"},
errMsg: "",
},
{
desc: "missing value #1",
tokens: []string{"name", "key", ":"},
errMsg: "invalid number of tokens",
},
{
desc: "missing value #2",
tokens: []string{"name", "key", ":", "value", "key2", ":"},
errMsg: "invalid number of tokens",
},
{
desc: "empty stat name",
tokens: []string{"", "key", ":", "value"},
errMsg: "stat name shouldn't be empty",
},
} {
t.Run(tc.desc, func(t *testing.T) {
err := validateTokens(tc.tokens)
if tc.errMsg == "" {
require.NoError(t, err)
} else {
require.Error(t, err)
require.Contains(t, err.Error(), tc.errMsg)
}
})
}
}
func TestValidateStatProperty(t *testing.T) {
for _, tc := range []struct {
desc string
key string
value string
sep string
errMsg string
}{
{
desc: "success case",
key: "key",
value: "value",
sep: ":",
errMsg: "",
},
{
desc: "missing key",
key: "",
value: "value",
sep: ":",
errMsg: "key shouldn't be empty",
},
{
desc: "missing value",
key: "key",
value: "",
sep: ":",
errMsg: "value shouldn't be empty",
},
{
desc: "invalid separator",
key: "key",
value: "value",
sep: "#",
errMsg: "separator should be :",
},
} {
t.Run(tc.desc, func(t *testing.T) {
err := validateStatProperty(tc.key, tc.value, tc.sep)
if tc.errMsg == "" {
require.NoError(t, err)
} else {
require.Error(t, err)
require.Contains(t, err.Error(), tc.errMsg)
}
})
}
}

View File

@ -1,284 +0,0 @@
//go:build rocksdb
// +build rocksdb
package opendb
import (
"fmt"
"strconv"
)
const (
sum = "SUM"
count = "COUNT"
p50 = "P50"
p95 = "P95"
p99 = "P99"
p100 = "P100"
)
type statLoader struct {
// statMap contains map of stat objects returned by parseSerializedStats function
// example of stats:
// #1: rocksdb.block.cache.miss COUNT : 5
// #2: rocksdb.compaction.times.micros P50 : 21112 P95 : 21112 P99 : 21112 P100 : 21112 COUNT : 1 SUM : 21112
// #1 case will be cast into int64
// #2 case will be cast into float64Histogram
statMap map[string]*stat
// NOTE: some methods accumulate errors instead of returning them, these methods are private and not intended to use outside
errors []error
}
func newStatLoader(statMap map[string]*stat) *statLoader {
return &statLoader{
statMap: statMap,
errors: make([]error, 0),
}
}
type stats struct {
NumberKeysWritten int64
NumberKeysRead int64
NumberKeysUpdated int64
// total block cache misses
// BLOCK_CACHE_MISS == BLOCK_CACHE_INDEX_MISS +
// BLOCK_CACHE_FILTER_MISS +
// BLOCK_CACHE_DATA_MISS;
// BLOCK_CACHE_INDEX_MISS: # of times cache miss when accessing index block from block cache.
// BLOCK_CACHE_FILTER_MISS: # of times cache miss when accessing filter block from block cache.
// BLOCK_CACHE_DATA_MISS: # of times cache miss when accessing data block from block cache.
BlockCacheMiss int64
// total block cache hit
// BLOCK_CACHE_HIT == BLOCK_CACHE_INDEX_HIT +
// BLOCK_CACHE_FILTER_HIT +
// BLOCK_CACHE_DATA_HIT;
// BLOCK_CACHE_INDEX_HIT: # of times cache hit when accessing index block from block cache.
// BLOCK_CACHE_FILTER_HIT: # of times cache hit when accessing filter block from block cache.
// BLOCK_CACHE_DATA_HIT: # of times cache hit when accessing data block from block cache.
BlockCacheHit int64
// # of blocks added to block cache.
BlockCacheAdd int64
// # of failures when adding blocks to block cache.
BlockCacheAddFailures int64
BlockCacheIndexMiss int64
BlockCacheIndexHit int64
BlockCacheIndexBytesInsert int64
BlockCacheFilterMiss int64
BlockCacheFilterHit int64
BlockCacheFilterBytesInsert int64
BlockCacheDataMiss int64
BlockCacheDataHit int64
BlockCacheDataBytesInsert int64
CompactReadBytes int64 // Bytes read during compaction
CompactWriteBytes int64 // Bytes written during compaction
CompactionTimesMicros *float64Histogram
CompactionTimesCPUMicros *float64Histogram
NumFilesInSingleCompaction *float64Histogram
// Read amplification statistics.
// Read amplification can be calculated using this formula
// (READ_AMP_TOTAL_READ_BYTES / READ_AMP_ESTIMATE_USEFUL_BYTES)
//
// REQUIRES: ReadOptions::read_amp_bytes_per_bit to be enabled
// TODO(yevhenii): seems not working?
ReadAmpEstimateUsefulBytes int64 // Estimate of total bytes actually used.
ReadAmpTotalReadBytes int64 // Total size of loaded data blocks.
NumberFileOpens int64
NumberFileErrors int64
// # of times bloom filter has avoided file reads, i.e., negatives.
BloomFilterUseful int64
// # of times bloom FullFilter has not avoided the reads.
BloomFilterFullPositive int64
// # of times bloom FullFilter has not avoided the reads and data actually
// exist.
BloomFilterFullTruePositive int64
// # of memtable hits.
MemtableHit int64
// # of memtable misses.
MemtableMiss int64
// # of Get() queries served by L0
GetHitL0 int64
// # of Get() queries served by L1
GetHitL1 int64
// # of Get() queries served by L2 and up
GetHitL2AndUp int64
// The number of uncompressed bytes issued by DB::Put(), DB::Delete(),
// DB::Merge(), and DB::Write().
BytesWritten int64
// The number of uncompressed bytes read from DB::Get(). It could be
// either from memtables, cache, or table files.
// For the number of logical bytes read from DB::MultiGet(),
// please use NUMBER_MULTIGET_BYTES_READ.
BytesRead int64
// Writer has to wait for compaction or flush to finish.
StallMicros int64
DBWriteStallHistogram *float64Histogram
// Last level and non-last level read statistics
LastLevelReadBytes int64
LastLevelReadCount int64
NonLastLevelReadBytes int64
NonLastLevelReadCount int64
DBGetMicros *float64Histogram
DBWriteMicros *float64Histogram
// Value size distribution in each operation
BytesPerRead *float64Histogram
BytesPerWrite *float64Histogram
BytesPerMultiget *float64Histogram
// Time spent flushing memtable to disk
FlushMicros *float64Histogram
}
type float64Histogram struct {
Sum float64
Count float64
P50 float64
P95 float64
P99 float64
P100 float64
}
func (l *statLoader) error() error {
if len(l.errors) != 0 {
return fmt.Errorf("%v", l.errors)
}
return nil
}
func (l *statLoader) load() (*stats, error) {
stats := &stats{
NumberKeysWritten: l.getInt64StatValue("rocksdb.number.keys.written", count),
NumberKeysRead: l.getInt64StatValue("rocksdb.number.keys.read", count),
NumberKeysUpdated: l.getInt64StatValue("rocksdb.number.keys.updated", count),
BlockCacheMiss: l.getInt64StatValue("rocksdb.block.cache.miss", count),
BlockCacheHit: l.getInt64StatValue("rocksdb.block.cache.hit", count),
BlockCacheAdd: l.getInt64StatValue("rocksdb.block.cache.add", count),
BlockCacheAddFailures: l.getInt64StatValue("rocksdb.block.cache.add.failures", count),
BlockCacheIndexMiss: l.getInt64StatValue("rocksdb.block.cache.index.miss", count),
BlockCacheIndexHit: l.getInt64StatValue("rocksdb.block.cache.index.hit", count),
BlockCacheIndexBytesInsert: l.getInt64StatValue("rocksdb.block.cache.index.bytes.insert", count),
BlockCacheFilterMiss: l.getInt64StatValue("rocksdb.block.cache.filter.miss", count),
BlockCacheFilterHit: l.getInt64StatValue("rocksdb.block.cache.filter.hit", count),
BlockCacheFilterBytesInsert: l.getInt64StatValue("rocksdb.block.cache.filter.bytes.insert", count),
BlockCacheDataMiss: l.getInt64StatValue("rocksdb.block.cache.data.miss", count),
BlockCacheDataHit: l.getInt64StatValue("rocksdb.block.cache.data.hit", count),
BlockCacheDataBytesInsert: l.getInt64StatValue("rocksdb.block.cache.data.bytes.insert", count),
CompactReadBytes: l.getInt64StatValue("rocksdb.compact.read.bytes", count),
CompactWriteBytes: l.getInt64StatValue("rocksdb.compact.write.bytes", count),
CompactionTimesMicros: l.getFloat64HistogramStatValue("rocksdb.compaction.times.micros"),
CompactionTimesCPUMicros: l.getFloat64HistogramStatValue("rocksdb.compaction.times.cpu_micros"),
NumFilesInSingleCompaction: l.getFloat64HistogramStatValue("rocksdb.numfiles.in.singlecompaction"),
ReadAmpEstimateUsefulBytes: l.getInt64StatValue("rocksdb.read.amp.estimate.useful.bytes", count),
ReadAmpTotalReadBytes: l.getInt64StatValue("rocksdb.read.amp.total.read.bytes", count),
NumberFileOpens: l.getInt64StatValue("rocksdb.no.file.opens", count),
NumberFileErrors: l.getInt64StatValue("rocksdb.no.file.errors", count),
BloomFilterUseful: l.getInt64StatValue("rocksdb.bloom.filter.useful", count),
BloomFilterFullPositive: l.getInt64StatValue("rocksdb.bloom.filter.full.positive", count),
BloomFilterFullTruePositive: l.getInt64StatValue("rocksdb.bloom.filter.full.true.positive", count),
MemtableHit: l.getInt64StatValue("rocksdb.memtable.hit", count),
MemtableMiss: l.getInt64StatValue("rocksdb.memtable.miss", count),
GetHitL0: l.getInt64StatValue("rocksdb.l0.hit", count),
GetHitL1: l.getInt64StatValue("rocksdb.l1.hit", count),
GetHitL2AndUp: l.getInt64StatValue("rocksdb.l2andup.hit", count),
BytesWritten: l.getInt64StatValue("rocksdb.bytes.written", count),
BytesRead: l.getInt64StatValue("rocksdb.bytes.read", count),
StallMicros: l.getInt64StatValue("rocksdb.stall.micros", count),
DBWriteStallHistogram: l.getFloat64HistogramStatValue("rocksdb.db.write.stall"),
LastLevelReadBytes: l.getInt64StatValue("rocksdb.last.level.read.bytes", count),
LastLevelReadCount: l.getInt64StatValue("rocksdb.last.level.read.count", count),
NonLastLevelReadBytes: l.getInt64StatValue("rocksdb.non.last.level.read.bytes", count),
NonLastLevelReadCount: l.getInt64StatValue("rocksdb.non.last.level.read.count", count),
DBGetMicros: l.getFloat64HistogramStatValue("rocksdb.db.get.micros"),
DBWriteMicros: l.getFloat64HistogramStatValue("rocksdb.db.write.micros"),
BytesPerRead: l.getFloat64HistogramStatValue("rocksdb.bytes.per.read"),
BytesPerWrite: l.getFloat64HistogramStatValue("rocksdb.bytes.per.write"),
BytesPerMultiget: l.getFloat64HistogramStatValue("rocksdb.bytes.per.multiget"),
FlushMicros: l.getFloat64HistogramStatValue("rocksdb.db.flush.micros"),
}
err := l.error()
if err != nil {
return nil, err
}
return stats, nil
}
// getFloat64HistogramStatValue converts stat object into float64Histogram
func (l *statLoader) getFloat64HistogramStatValue(statName string) *float64Histogram {
return &float64Histogram{
Sum: l.getFloat64StatValue(statName, sum),
Count: l.getFloat64StatValue(statName, count),
P50: l.getFloat64StatValue(statName, p50),
P95: l.getFloat64StatValue(statName, p95),
P99: l.getFloat64StatValue(statName, p99),
P100: l.getFloat64StatValue(statName, p100),
}
}
// getInt64StatValue converts property of stat object into int64
func (l *statLoader) getInt64StatValue(statName, propName string) int64 {
stringVal := l.getStatValue(statName, propName)
if stringVal == "" {
l.errors = append(l.errors, fmt.Errorf("can't get stat by name: %v", statName))
return 0
}
intVal, err := strconv.ParseInt(stringVal, 10, 64)
if err != nil {
l.errors = append(l.errors, fmt.Errorf("can't parse int: %v", err))
return 0
}
return intVal
}
// getFloat64StatValue converts property of stat object into float64
func (l *statLoader) getFloat64StatValue(statName, propName string) float64 {
stringVal := l.getStatValue(statName, propName)
if stringVal == "" {
l.errors = append(l.errors, fmt.Errorf("can't get stat by name: %v", statName))
return 0
}
floatVal, err := strconv.ParseFloat(stringVal, 64)
if err != nil {
l.errors = append(l.errors, fmt.Errorf("can't parse float: %v", err))
return 0
}
return floatVal
}
// getStatValue gets property of stat object
func (l *statLoader) getStatValue(statName, propName string) string {
stat, ok := l.statMap[statName]
if !ok {
l.errors = append(l.errors, fmt.Errorf("stat %v doesn't exist", statName))
return ""
}
prop, ok := stat.props[propName]
if !ok {
l.errors = append(l.errors, fmt.Errorf("stat %v doesn't have %v property", statName, propName))
return ""
}
return prop
}

View File

@ -1,90 +0,0 @@
//go:build rocksdb
// +build rocksdb
package opendb
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestStatsLoader(t *testing.T) {
defaultStat := stat{
props: map[string]string{
"COUNT": "1",
},
}
defaultHistogramStat := stat{
props: map[string]string{
"P50": "1",
"P95": "2",
"P99": "3",
"P100": "4",
"COUNT": "5",
"SUM": "6",
},
}
defaultStatMap := map[string]*stat{
"rocksdb.number.keys.written": &defaultStat,
"rocksdb.number.keys.read": &defaultStat,
"rocksdb.number.keys.updated": &defaultStat,
"rocksdb.block.cache.miss": &defaultStat,
"rocksdb.block.cache.hit": &defaultStat,
"rocksdb.block.cache.add": &defaultStat,
"rocksdb.block.cache.add.failures": &defaultStat,
"rocksdb.block.cache.index.miss": &defaultStat,
"rocksdb.block.cache.index.hit": &defaultStat,
"rocksdb.block.cache.index.bytes.insert": &defaultStat,
"rocksdb.block.cache.filter.miss": &defaultStat,
"rocksdb.block.cache.filter.hit": &defaultStat,
"rocksdb.block.cache.filter.bytes.insert": &defaultStat,
"rocksdb.block.cache.data.miss": &defaultStat,
"rocksdb.block.cache.data.hit": &defaultStat,
"rocksdb.block.cache.data.bytes.insert": &defaultStat,
"rocksdb.compact.read.bytes": &defaultStat,
"rocksdb.compact.write.bytes": &defaultStat,
"rocksdb.compaction.times.micros": &defaultHistogramStat,
"rocksdb.compaction.times.cpu_micros": &defaultHistogramStat,
"rocksdb.numfiles.in.singlecompaction": &defaultHistogramStat,
"rocksdb.read.amp.estimate.useful.bytes": &defaultStat,
"rocksdb.read.amp.total.read.bytes": &defaultStat,
"rocksdb.no.file.opens": &defaultStat,
"rocksdb.no.file.errors": &defaultStat,
"rocksdb.bloom.filter.useful": &defaultStat,
"rocksdb.bloom.filter.full.positive": &defaultStat,
"rocksdb.bloom.filter.full.true.positive": &defaultStat,
"rocksdb.memtable.hit": &defaultStat,
"rocksdb.memtable.miss": &defaultStat,
"rocksdb.l0.hit": &defaultStat,
"rocksdb.l1.hit": &defaultStat,
"rocksdb.l2andup.hit": &defaultStat,
"rocksdb.bytes.written": &defaultStat,
"rocksdb.bytes.read": &defaultStat,
"rocksdb.stall.micros": &defaultStat,
"rocksdb.db.write.stall": &defaultHistogramStat,
"rocksdb.last.level.read.bytes": &defaultStat,
"rocksdb.last.level.read.count": &defaultStat,
"rocksdb.non.last.level.read.bytes": &defaultStat,
"rocksdb.non.last.level.read.count": &defaultStat,
"rocksdb.db.get.micros": &defaultHistogramStat,
"rocksdb.db.write.micros": &defaultHistogramStat,
"rocksdb.bytes.per.read": &defaultHistogramStat,
"rocksdb.bytes.per.write": &defaultHistogramStat,
"rocksdb.bytes.per.multiget": &defaultHistogramStat,
"rocksdb.db.flush.micros": &defaultHistogramStat,
}
statLoader := newStatLoader(defaultStatMap)
stats, err := statLoader.load()
require.NoError(t, err)
require.Equal(t, stats.NumberKeysWritten, int64(1))
require.Equal(t, stats.NumberKeysRead, int64(1))
require.Equal(t, stats.CompactionTimesMicros.P50, float64(1))
require.Equal(t, stats.CompactionTimesMicros.P95, float64(2))
require.Equal(t, stats.CompactionTimesMicros.P99, float64(3))
require.Equal(t, stats.CompactionTimesMicros.P100, float64(4))
require.Equal(t, stats.CompactionTimesMicros.Count, float64(5))
require.Equal(t, stats.CompactionTimesMicros.Sum, float64(6))
}

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
"private": true, "private": true,
"description": "Solidity contracts for 0g Blockchain", "description": "Solidity contracts for 0g Blockchain",
"engines": { "engines": {
"node": ">=18.0.0" "node": ">=20.0.0"
}, },
"scripts": { "scripts": {
"build": "npm run clean && npm run compile && npm run ethermint-json", "build": "npm run clean && npm run compile && npm run ethermint-json",
@ -23,14 +23,14 @@
"test": "hardhat test" "test": "hardhat test"
}, },
"devDependencies": { "devDependencies": {
"@nomicfoundation/hardhat-toolbox": "^2.0.2", "@nomicfoundation/hardhat-toolbox": "^5.0.0",
"@openzeppelin/contracts": "4.8.3", "@openzeppelin/contracts": "4.8.3",
"@typescript-eslint/eslint-plugin": "^5.59.6", "@typescript-eslint/eslint-plugin": "^5.59.6",
"@typescript-eslint/parser": "^5.59.6", "@typescript-eslint/parser": "^5.59.6",
"eslint": "^8.40.0", "eslint": "^8.40.0",
"eslint-config-prettier": "8.8.0", "eslint-config-prettier": "8.8.0",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"hardhat": "^2.14.0", "hardhat": "^2.22.8",
"prettier": "2.8.8", "prettier": "2.8.8",
"prettier-plugin-solidity": "^1.1.3", "prettier-plugin-solidity": "^1.1.3",
"solhint": "^3.4.1", "solhint": "^3.4.1",

View File

@ -26,7 +26,7 @@ rm -rf $DATA
BINARY=kava BINARY=kava
# Create new data directory, overwriting any that alread existed # Create new data directory, overwriting any that already existed
chainID="kavalocalnet_8888-1" chainID="kavalocalnet_8888-1"
$BINARY init validator --chain-id $chainID $BINARY init validator --chain-id $chainID

File diff suppressed because it is too large Load Diff

123
go.mod
View File

@ -4,61 +4,62 @@ go 1.21
require ( require (
cosmossdk.io/errors v1.0.1 cosmossdk.io/errors v1.0.1
cosmossdk.io/log v1.3.1
cosmossdk.io/math v1.3.0 cosmossdk.io/math v1.3.0
cosmossdk.io/simapp v0.0.0-20231127212628-044ff4d8c015 cosmossdk.io/simapp v0.0.0-20231127212628-044ff4d8c015
github.com/Kava-Labs/opendb v0.0.0-20240719173129-a2f11f6d7e51
github.com/cenkalti/backoff/v4 v4.1.3 github.com/cenkalti/backoff/v4 v4.1.3
github.com/cometbft/cometbft v0.37.4 github.com/cometbft/cometbft v0.37.9
github.com/cometbft/cometbft-db v0.9.1 github.com/cometbft/cometbft-db v0.9.1
github.com/coniks-sys/coniks-go v0.0.0-20180722014011-11acf4819b71 github.com/coniks-sys/coniks-go v0.0.0-20180722014011-11acf4819b71
github.com/consensys/gnark-crypto v0.12.1 github.com/consensys/gnark-crypto v0.12.1
github.com/cosmos/cosmos-proto v1.0.0-beta.4 github.com/cosmos/cosmos-db v1.0.2
github.com/cosmos/cosmos-proto v1.0.0-beta.5
github.com/cosmos/cosmos-sdk v0.47.10 github.com/cosmos/cosmos-sdk v0.47.10
github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/go-bip39 v1.0.0
github.com/cosmos/gogoproto v1.4.10 github.com/cosmos/gogoproto v1.4.10
github.com/cosmos/iavl v0.20.1 github.com/cosmos/iavl v1.2.0
github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3 github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3
github.com/cosmos/ibc-go/modules/light-clients/08-wasm v0.1.1-ibc-go-v7.3-wasmvm-v1.5 github.com/cosmos/ibc-go/modules/light-clients/08-wasm v0.1.1-ibc-go-v7.3-wasmvm-v1.5
github.com/cosmos/ibc-go/v7 v7.4.0 github.com/cosmos/ibc-go/v7 v7.4.0
github.com/ethereum/go-ethereum v1.10.26 github.com/ethereum/go-ethereum v1.10.26
github.com/evmos/ethermint v0.21.0 github.com/evmos/ethermint v0.21.0
github.com/go-kit/kit v0.12.0
github.com/gogo/protobuf v1.3.2 github.com/gogo/protobuf v1.3.2
github.com/golang/protobuf v1.5.3 github.com/golang/protobuf v1.5.4
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0
github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/linxGnu/grocksdb v1.8.6 github.com/linxGnu/grocksdb v1.8.13
github.com/pelletier/go-toml/v2 v2.1.0 github.com/pelletier/go-toml/v2 v2.1.0
github.com/prometheus/client_golang v1.14.0
github.com/shopspring/decimal v1.4.0 github.com/shopspring/decimal v1.4.0
github.com/spf13/cast v1.6.0 github.com/spf13/cast v1.6.0
github.com/spf13/cobra v1.7.0 github.com/spf13/cobra v1.8.0
github.com/spf13/viper v1.16.0 github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.9.0
github.com/subosito/gotenv v1.6.0 github.com/subosito/gotenv v1.6.0
golang.org/x/crypto v0.24.0 golang.org/x/crypto v0.24.0
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 golang.org/x/exp v0.0.0-20230905200255-921286631fa9
google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de
google.golang.org/grpc v1.60.1 google.golang.org/grpc v1.63.2
google.golang.org/protobuf v1.32.0 google.golang.org/protobuf v1.33.0
sigs.k8s.io/yaml v1.4.0 sigs.k8s.io/yaml v1.4.0
) )
require ( require (
cloud.google.com/go v0.111.0 // indirect cloud.google.com/go v0.112.0 // indirect
cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute v1.24.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v1.1.5 // indirect cloud.google.com/go/iam v1.1.6 // indirect
cloud.google.com/go/storage v1.35.1 // indirect cloud.google.com/go/storage v1.36.0 // indirect
cosmossdk.io/api v0.3.1 // indirect cosmossdk.io/api v0.3.1 // indirect
cosmossdk.io/core v0.6.1 // indirect cosmossdk.io/core v0.6.1 // indirect
cosmossdk.io/depinject v1.0.0-alpha.4 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect
cosmossdk.io/log v1.3.1 // indirect
cosmossdk.io/tools/rosetta v0.2.1 // indirect cosmossdk.io/tools/rosetta v0.2.1 // indirect
filippo.io/edwards25519 v1.0.0 // indirect filippo.io/edwards25519 v1.0.0 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/99designs/keyring v1.2.1 // indirect github.com/99designs/keyring v1.2.1 // indirect
github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect
github.com/CosmWasm/wasmvm v1.5.2 // indirect github.com/CosmWasm/wasmvm v1.5.2 // indirect
github.com/DataDog/zstd v1.5.5 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect github.com/StackExchange/wmi v1.2.1 // indirect
github.com/VictoriaMetrics/fastcache v1.6.0 // indirect github.com/VictoriaMetrics/fastcache v1.6.0 // indirect
github.com/armon/go-metrics v0.4.1 // indirect github.com/armon/go-metrics v0.4.1 // indirect
@ -67,30 +68,32 @@ require (
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect
github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/bits-and-blooms/bitset v1.7.0 // indirect
github.com/btcsuite/btcd v0.23.4 // indirect github.com/btcsuite/btcd v0.24.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
github.com/btcsuite/btcd/btcutil v1.1.3 // indirect github.com/btcsuite/btcd/btcutil v1.1.5 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/chzyer/readline v1.5.1 // indirect github.com/chzyer/readline v1.5.1 // indirect
github.com/cockroachdb/apd/v2 v2.0.2 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect
github.com/cockroachdb/errors v1.10.0 // indirect github.com/cockroachdb/errors v1.11.1 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/pebble v1.1.0 // indirect
github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/coinbase/rosetta-sdk-go v0.7.9 // indirect github.com/coinbase/rosetta-sdk-go v0.7.9 // indirect
github.com/confio/ics23/go v0.9.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect
github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/bavard v0.1.13 // indirect
github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/btcutil v1.0.5 // indirect
github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect
github.com/cosmos/ics23/go v0.10.0 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect
github.com/cosmos/ledger-cosmos-go v0.13.1 // indirect github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect
github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect
github.com/creachadair/taskgroup v0.4.2 // indirect github.com/creachadair/taskgroup v0.4.2 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/deckarep/golang-set v1.8.0 // indirect github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect
@ -100,20 +103,22 @@ require (
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dvsekhvalnov/jose2go v1.6.0 // indirect github.com/dvsekhvalnov/jose2go v1.6.0 // indirect
github.com/edsrzf/mmap-go v1.0.0 // indirect github.com/edsrzf/mmap-go v1.0.0 // indirect
github.com/felixge/httpsnoop v1.0.2 // indirect github.com/emicklei/dot v1.6.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
github.com/getsentry/sentry-go v0.23.0 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect
github.com/go-kit/kit v0.13.0 // indirect
github.com/go-kit/log v0.2.1 // indirect github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
github.com/go-stack/stack v1.8.1 // indirect github.com/go-stack/stack v1.8.1 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/googleapis v1.4.1 // indirect
github.com/golang/glog v1.1.2 // indirect github.com/golang/glog v1.2.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect github.com/golang/mock v1.6.0 // indirect
github.com/golang/snappy v0.0.4 // indirect github.com/golang/snappy v0.0.4 // indirect
@ -121,7 +126,7 @@ require (
github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-cmp v0.6.0 // indirect
github.com/google/orderedcode v0.0.1 // indirect github.com/google/orderedcode v0.0.1 // indirect
github.com/google/s2a-go v0.1.7 // indirect github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.4.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/handlers v1.5.1 // indirect
@ -131,11 +136,12 @@ require (
github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/merlin v0.1.1 // indirect
github.com/gtank/ristretto255 v0.1.2 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-getter v1.7.1 // indirect github.com/hashicorp/go-getter v1.7.5 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hdevalence/ed25519consensus v0.1.0 // indirect github.com/hdevalence/ed25519consensus v0.1.0 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
@ -148,11 +154,10 @@ require (
github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect
github.com/klauspost/compress v1.17.0 // indirect github.com/klauspost/compress v1.17.7 // indirect
github.com/kr/pretty v0.3.1 // indirect github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect github.com/kr/text v0.2.0 // indirect
github.com/lib/pq v1.10.7 // indirect github.com/lib/pq v1.10.7 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect github.com/magiconair/properties v1.8.7 // indirect
github.com/manifoldco/promptui v0.9.0 // indirect github.com/manifoldco/promptui v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
@ -167,28 +172,33 @@ require (
github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/mtibben/percent v0.2.1 // indirect github.com/mtibben/percent v0.2.1 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect github.com/prometheus/procfs v0.13.0 // indirect
github.com/prometheus/tsdb v0.7.1 // indirect github.com/prometheus/tsdb v0.7.1 // indirect
github.com/rakyll/statik v0.1.7 // indirect github.com/rakyll/statik v0.1.7 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rjeczalik/notify v0.9.1 // indirect github.com/rjeczalik/notify v0.9.1 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/rs/cors v1.8.3 // indirect github.com/rs/cors v1.8.3 // indirect
github.com/rs/zerolog v1.32.0 // indirect github.com/rs/zerolog v1.32.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
github.com/status-im/keycard-go v0.2.0 // indirect github.com/status-im/keycard-go v0.2.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
github.com/tendermint/go-amino v0.16.0 // indirect github.com/tendermint/go-amino v0.16.0 // indirect
github.com/tidwall/btree v1.6.0 // indirect github.com/tidwall/btree v1.7.0 // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect github.com/tklauser/numcpus v0.4.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect
@ -197,20 +207,24 @@ require (
github.com/zondax/ledger-go v0.14.3 // indirect github.com/zondax/ledger-go v0.14.3 // indirect
go.etcd.io/bbolt v1.3.8 // indirect go.etcd.io/bbolt v1.3.8 // indirect
go.opencensus.io v0.24.0 // indirect go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/otel v1.19.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect
go.opentelemetry.io/otel/metric v1.19.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect
go.opentelemetry.io/otel/trace v1.19.0 // indirect go.opentelemetry.io/otel v1.22.0 // indirect
golang.org/x/net v0.21.0 // indirect go.opentelemetry.io/otel/metric v1.22.0 // indirect
golang.org/x/oauth2 v0.15.0 // indirect go.opentelemetry.io/otel/trace v1.22.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/oauth2 v0.17.0 // indirect
golang.org/x/sync v0.7.0 // indirect golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.21.0 // indirect golang.org/x/sys v0.21.0 // indirect
golang.org/x/term v0.21.0 // indirect golang.org/x/term v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.5.0 // indirect golang.org/x/time v0.5.0 // indirect
google.golang.org/api v0.153.0 // indirect google.golang.org/api v0.162.0 // indirect
google.golang.org/appengine v1.6.8 // indirect google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
@ -224,20 +238,23 @@ replace (
// Use the cosmos keyring code // Use the cosmos keyring code
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
// Use cometbft fork of tendermint // Use cometbft fork of tendermint
github.com/cometbft/cometbft => github.com/kava-labs/cometbft v0.37.4-kava.1 github.com/cometbft/cometbft => github.com/kava-labs/cometbft v0.37.9-kava.1
github.com/cometbft/cometbft-db => github.com/kava-labs/cometbft-db v0.9.1-kava.1 github.com/cometbft/cometbft-db => github.com/kava-labs/cometbft-db v0.9.1-kava.2
// Use cosmos-sdk fork with backported fix for unsafe-reset-all, staking transfer events, and custom tally handler support // Use cosmos-sdk fork with backported fix for unsafe-reset-all, staking transfer events, and custom tally handler support
// github.com/cosmos/cosmos-sdk => github.com/0glabs/cosmos-sdk v0.46.11-kava.3 // github.com/cosmos/cosmos-sdk => github.com/0glabs/cosmos-sdk v0.46.11-kava.3
github.com/cosmos/cosmos-sdk => github.com/0glabs/cosmos-sdk v0.47.10-0glabs.3 github.com/cosmos/cosmos-sdk => github.com/0glabs/cosmos-sdk v0.47.10-0glabs.5
github.com/cosmos/iavl => github.com/kava-labs/iavl v1.2.0-kava.1
// See https://github.com/cosmos/cosmos-sdk/pull/13093 // See https://github.com/cosmos/cosmos-sdk/pull/13093
github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2 github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2
// Use go-ethereum fork with precompiles // Tracking kava-labs/go-ethereum kava/release/v1.10 branch
// TODO: Tag before release
github.com/ethereum/go-ethereum => github.com/evmos/go-ethereum v1.10.26-evmos-rc2 github.com/ethereum/go-ethereum => github.com/evmos/go-ethereum v1.10.26-evmos-rc2
// Use ethermint fork that respects min-gas-price with NoBaseFee true and london enabled, and includes eip712 support // Use ethermint fork that respects min-gas-price with NoBaseFee true and london enabled, and includes eip712 support
github.com/evmos/ethermint => github.com/0glabs/ethermint v0.21.0-0g.v3.0.3 github.com/evmos/ethermint => github.com/0glabs/ethermint v0.21.0-0g.v3.1.2
// See https://github.com/cosmos/cosmos-sdk/pull/10401, https://github.com/cosmos/cosmos-sdk/commit/0592ba6158cd0bf49d894be1cef4faeec59e8320 // See https://github.com/cosmos/cosmos-sdk/pull/10401, https://github.com/cosmos/cosmos-sdk/commit/0592ba6158cd0bf49d894be1cef4faeec59e8320
github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.0 github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.0
// Downgraded to avoid bugs in following commits which causes "version does not exist" errors // Downgraded to avoid bugs in following commits which causes "version does not exist" errors
github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
// Avoid change in slices.SortFunc, see https://github.com/cosmos/cosmos-sdk/issues/20159
golang.org/x/exp => golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb golang.org/x/exp => golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb
) )

244
go.sum
View File

@ -32,8 +32,8 @@ cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w9
cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU=
cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA=
cloud.google.com/go v0.111.0 h1:YHLKNupSD1KqjDbQ3+LVdQ81h/UJbJyZG203cEfnQgM= cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM=
cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU= cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4=
cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw=
cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY=
cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI=
@ -71,8 +71,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU=
cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg=
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I=
@ -112,8 +112,8 @@ cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y97
cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc=
cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc=
cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc=
cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI=
cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic=
cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI=
cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8=
@ -174,8 +174,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc=
cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s=
cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w= cloud.google.com/go/storage v1.36.0 h1:P0mOkAcaJxhCTvAkMhxMfrTKiNcub4YmmPBtlhAyTr8=
cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8=
cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw=
cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g=
cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU=
@ -209,10 +209,10 @@ filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3/go.mod h1:wMEGFFFNuPos7vHmWXfszqImLppbc0wEhh6JBfJIUgw= git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3/go.mod h1:wMEGFFFNuPos7vHmWXfszqImLppbc0wEhh6JBfJIUgw=
git.sr.ht/~sircmpwn/go-bare v0.0.0-20210406120253-ab86bc2846d9/go.mod h1:BVJwbDfVjCjoFiKrhkei6NdGcZYpkDkdyCdg1ukytRA= git.sr.ht/~sircmpwn/go-bare v0.0.0-20210406120253-ab86bc2846d9/go.mod h1:BVJwbDfVjCjoFiKrhkei6NdGcZYpkDkdyCdg1ukytRA=
github.com/0glabs/cosmos-sdk v0.47.10-0glabs.3 h1:Wx3tVMTuFaaHDeJT/OzT7QLfAIpeaZsG9R6XoTOyKCw= github.com/0glabs/cosmos-sdk v0.47.10-0glabs.5 h1:CwL3i7ccMjOXpKnJ9w0WkM7UpTWLXa/W2ZAwpxFUfb8=
github.com/0glabs/cosmos-sdk v0.47.10-0glabs.3/go.mod h1:BWo24B8cApWcO2/widWYIdt3CPxbh+HCSypCPpjTjog= github.com/0glabs/cosmos-sdk v0.47.10-0glabs.5/go.mod h1:KskIVnhXTFqrw7CDccMvx7To5KzUsOomIsQV7sPGOog=
github.com/0glabs/ethermint v0.21.0-0g.v3.0.3 h1:QNrXBQV5L/9FvYRUzJRXMV745xBmJhIP0aEdo0u8x+8= github.com/0glabs/ethermint v0.21.0-0g.v3.1.2 h1:qSTk1t5u3ppN/00bBaZYBF4+GiFlyr+92UlcWW2J8Zg=
github.com/0glabs/ethermint v0.21.0-0g.v3.0.3/go.mod h1:HYQUhvcZBIG71H3xlxQSk0XyQEjeaHsduOj6O2QImrE= github.com/0glabs/ethermint v0.21.0-0g.v3.1.2/go.mod h1:MjUzm+q5TiZIBNVq29B3a5Lx0A946QXBBvSSqD4l8ks=
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs=
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4=
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM=
@ -229,9 +229,13 @@ github.com/CosmWasm/wasmvm v1.5.2/go.mod h1:Q0bSEtlktzh7W2hhEaifrFp1Erx11ckQZmjq
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ=
github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Kava-Labs/opendb v0.0.0-20240719173129-a2f11f6d7e51 h1:tMTENCeSPIJO8yCpEQbT15XYXt4EFNQUx3s334uxVts=
github.com/Kava-Labs/opendb v0.0.0-20240719173129-a2f11f6d7e51/go.mod h1:LbPsJiWvj90NT3Y9YV8EFPkWfvp8A15Tp88qqKa3LxA=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
@ -303,9 +307,9 @@ github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13P
github.com/btcsuite/btcd v0.21.0-beta.0.20201114000516-e9c7a5ac6401/go.mod h1:Sv4JPQ3/M+teHz9Bo5jBpkNcP0x6r7rdihlNL/7tTAs= github.com/btcsuite/btcd v0.21.0-beta.0.20201114000516-e9c7a5ac6401/go.mod h1:Sv4JPQ3/M+teHz9Bo5jBpkNcP0x6r7rdihlNL/7tTAs=
github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M=
github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y=
github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A=
github.com/btcsuite/btcd v0.23.4 h1:IzV6qqkfwbItOS/sg/aDfPDsjPP8twrCOE2R93hxMlQ= github.com/btcsuite/btcd v0.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo=
github.com/btcsuite/btcd v0.23.4/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd v0.24.0/go.mod h1:K4IDc1593s8jKXIF7yS7yCTSxrknB9z0STzc2j6XgE4=
github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA=
github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
@ -313,11 +317,12 @@ github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf
github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A=
github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE=
github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8=
github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ=
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
@ -349,8 +354,8 @@ github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
@ -378,15 +383,23 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ=
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM=
github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E=
github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/cockroachdb/errors v1.10.0 h1:lfxS8zZz1+OjtV4MtNWgboi/W5tyLEB6VQZBXN+0VUU= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4=
github.com/cockroachdb/errors v1.10.0/go.mod h1:lknhIsEVQ9Ss/qKDBQS/UqFSvPQjOwNq2qyKAxtHRqE= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8=
github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw=
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
github.com/cockroachdb/pebble v1.1.0 h1:pcFh8CdCIt2kmEpK0OIatq67Ln9uGDYY3d5XnE0LJG4=
github.com/cockroachdb/pebble v1.1.0/go.mod h1:sEHm5NOXxyiAoKWhoFxT8xMgd/f3RA6qUqQ1BXKrh2E=
github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/coinbase/kryptology v1.8.0/go.mod h1:RYXOAPdzOGUe3qlSFkMGn58i3xUA8hmxYHksuq+8ciI= github.com/coinbase/kryptology v1.8.0/go.mod h1:RYXOAPdzOGUe3qlSFkMGn58i3xUA8hmxYHksuq+8ciI=
github.com/coinbase/rosetta-sdk-go v0.7.9 h1:lqllBjMnazTjIqYrOGv8h8jxjg9+hJazIGZr9ZvoCcA= github.com/coinbase/rosetta-sdk-go v0.7.9 h1:lqllBjMnazTjIqYrOGv8h8jxjg9+hJazIGZr9ZvoCcA=
@ -413,8 +426,10 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk=
github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis=
github.com/cosmos/cosmos-proto v1.0.0-beta.4 h1:aEL7tU/rLOmxZQ9z4i7mzxcLbSCY48OdY7lIWTLG7oU= github.com/cosmos/cosmos-db v1.0.2 h1:hwMjozuY1OlJs/uh6vddqnk9j7VamLv+0DBlbEXbAKs=
github.com/cosmos/cosmos-proto v1.0.0-beta.4/go.mod h1:oeB+FyVzG3XrQJbJng0EnV8Vljfk9XvTIpGILNU/9Co= github.com/cosmos/cosmos-db v1.0.2/go.mod h1:Z8IXcFJ9PqKK6BIsVOB3QXtkKoqUOp1vRvPT39kOXEA=
github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA=
github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec=
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
@ -423,8 +438,6 @@ github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ
github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU=
github.com/cosmos/gogoproto v1.4.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoKuI= github.com/cosmos/gogoproto v1.4.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoKuI=
github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek= github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek=
github.com/cosmos/iavl v0.20.1 h1:rM1kqeG3/HBT85vsZdoSNsehciqUQPWrR4BYmqE2+zg=
github.com/cosmos/iavl v0.20.1/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A=
github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3 h1:MZGDMETv72suFpTAD6VPGqSIm1FJcChtk2HmVh9D+Bo= github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3 h1:MZGDMETv72suFpTAD6VPGqSIm1FJcChtk2HmVh9D+Bo=
github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3/go.mod h1:UvDmcGIWJPIytq+Q78/ff5NTOsuX/7IrNgEugTW5i0s= github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3/go.mod h1:UvDmcGIWJPIytq+Q78/ff5NTOsuX/7IrNgEugTW5i0s=
github.com/cosmos/ibc-go/modules/light-clients/08-wasm v0.1.1-ibc-go-v7.3-wasmvm-v1.5 h1:sMoHjep+KInjMrppNCEutMVm1p8nI9WhKCuMQ+EcUHw= github.com/cosmos/ibc-go/modules/light-clients/08-wasm v0.1.1-ibc-go-v7.3-wasmvm-v1.5 h1:sMoHjep+KInjMrppNCEutMVm1p8nI9WhKCuMQ+EcUHw=
@ -435,15 +448,16 @@ github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZD
github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0=
github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo=
github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA=
github.com/cosmos/ledger-cosmos-go v0.13.1 h1:12ac9+GwBb9BjP7X5ygpFk09Itwzjzfmg6A2CWFjoVs= github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM=
github.com/cosmos/ledger-cosmos-go v0.13.1/go.mod h1:5tv2RVJEd2+Y38TIQN4CRjJeQGyqOEiKJDfqhk5UjqE= github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8=
github.com/cosmos/rosetta-sdk-go v0.10.0 h1:E5RhTruuoA7KTIXUcMicL76cffyeoyvNybzUGSKFTcM= github.com/cosmos/rosetta-sdk-go v0.10.0 h1:E5RhTruuoA7KTIXUcMicL76cffyeoyvNybzUGSKFTcM=
github.com/cosmos/rosetta-sdk-go v0.10.0/go.mod h1:SImAZkb96YbwvoRkzSMQB6noNJXFgWl/ENIznEoYQI4= github.com/cosmos/rosetta-sdk-go v0.10.0/go.mod h1:SImAZkb96YbwvoRkzSMQB6noNJXFgWl/ENIznEoYQI4=
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8= github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8=
github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
@ -459,11 +473,12 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=
github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M=
github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw=
@ -504,6 +519,8 @@ github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFP
github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/emicklei/dot v1.6.1 h1:ujpDlBkkwgWUY+qPId5IwapRW/xEoligRSYjioR6DFI=
github.com/emicklei/dot v1.6.1/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -515,13 +532,15 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
github.com/evmos/go-ethereum v1.10.26-evmos-rc2 h1:tYghk1ZZ8X4/OQ4YI9hvtm8aSN8OSqO0g9vo/sCMdBo= github.com/evmos/go-ethereum v1.10.26-evmos-rc2 h1:tYghk1ZZ8X4/OQ4YI9hvtm8aSN8OSqO0g9vo/sCMdBo=
github.com/evmos/go-ethereum v1.10.26-evmos-rc2/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo= github.com/evmos/go-ethereum v1.10.26-evmos-rc2/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
@ -541,8 +560,8 @@ github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqG
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/getsentry/sentry-go v0.23.0 h1:dn+QRCeJv4pPt9OjVXiMcGIBIefaTJPw/h0bZWO05nE= github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
github.com/getsentry/sentry-go v0.23.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
@ -556,8 +575,8 @@ github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3Bop
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU=
github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg=
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@ -566,8 +585,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
@ -620,8 +639,8 @@ github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -656,8 +675,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
@ -723,8 +742,8 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
@ -780,8 +799,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= github.com/hashicorp/go-getter v1.7.5 h1:dT58k9hQ/vbxNMwoI5+xFYAJuv6152UNvdHokfI5wE4=
github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= github.com/hashicorp/go-getter v1.7.5/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
@ -802,8 +821,11 @@ github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs=
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
@ -880,10 +902,12 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0=
github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
github.com/kava-labs/cometbft v0.37.4-kava.1 h1:QRuyBieWdUBpe4pcXgzu1SdMH2lkTaqXr/JPIeqdiHE= github.com/kava-labs/cometbft v0.37.9-kava.1 h1:0mMsAhpV8p0peD9sabIZ//M4nP6LiiZ0o34gfuHdANY=
github.com/kava-labs/cometbft v0.37.4-kava.1/go.mod h1:Cmg5Hp4sNpapm7j+x0xRyt2g0juQfmB752ous+pA0G8= github.com/kava-labs/cometbft v0.37.9-kava.1/go.mod h1:j0Q3RqrCd+cztWCugs3obbzC4NyHGBPZZjtm/fWV00I=
github.com/kava-labs/cometbft-db v0.9.1-kava.1 h1:0KmSPdXYdRp6TsgKuMxRnMZCMEGC5ysIVjuJddYr4tw= github.com/kava-labs/cometbft-db v0.9.1-kava.2 h1:ZQaio886ifvml9XtJB4IYHhlArgA3+/a5Zwidg7H2J8=
github.com/kava-labs/cometbft-db v0.9.1-kava.1/go.mod h1:iliyWaoV0mRwBJoizElCwwRA9Tf7jZJOURcRZF9m60U= github.com/kava-labs/cometbft-db v0.9.1-kava.2/go.mod h1:PvUZbx7zeR7I4CAvtKBoii/5ia5gXskKjDjIVpt7gDw=
github.com/kava-labs/iavl v1.2.0-kava.1 h1:HPme3nVrR25XshEFDckMg6fp0tVfpAjTi32/5Iiyuzk=
github.com/kava-labs/iavl v1.2.0-kava.1/go.mod h1:HidWWLVAtODJqFD6Hbne2Y0q3SdxByJepHUOeoH4LiI=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@ -894,8 +918,8 @@ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio=
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
@ -925,12 +949,10 @@ github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ic
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/linxGnu/grocksdb v1.8.6 h1:O7I6SIGPrypf3f/gmrrLUBQDKfO8uOoYdWf4gLS06tc= github.com/linxGnu/grocksdb v1.8.13 h1:X3Id7Obhf8qLY9WPc4LmmtIyabmdDf810XSFDnLlW7E=
github.com/linxGnu/grocksdb v1.8.6/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= github.com/linxGnu/grocksdb v1.8.13/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA=
github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4= github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@ -1067,6 +1089,8 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
@ -1077,8 +1101,8 @@ github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9
github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67 h1:jik8PHtAIsPlCRJjJzl4udgEf7hawInF9texMeO2jrU=
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
@ -1109,8 +1133,8 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
@ -1127,8 +1151,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g=
github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
@ -1145,8 +1169,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo=
github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
@ -1159,6 +1183,10 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0=
github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM=
@ -1182,6 +1210,8 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
@ -1193,18 +1223,16 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA=
github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg=
@ -1214,8 +1242,9 @@ github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5J
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@ -1227,8 +1256,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
@ -1236,8 +1266,8 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E=
github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI=
github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.14.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.14.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
@ -1308,22 +1338,30 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs=
go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ=
go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08=
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw=
go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y=
go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI=
go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg=
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY=
go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0=
go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/mock v0.2.0 h1:TaP3xedm7JaAgScZO7tlvlKrqT0p7I6OsdGB5YNSMDU= go.uber.org/mock v0.2.0 h1:TaP3xedm7JaAgScZO7tlvlKrqT0p7I6OsdGB5YNSMDU=
go.uber.org/mock v0.2.0/go.mod h1:J0y0rp9L3xiff1+ZBfKxlC1fz2+aO16tw0tsDOixfuM= go.uber.org/mock v0.2.0/go.mod h1:J0y0rp9L3xiff1+ZBfKxlC1fz2+aO16tw0tsDOixfuM=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
@ -1452,8 +1490,8 @@ golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfS
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1479,8 +1517,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -1765,8 +1803,8 @@ google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ
google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70=
google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4= google.golang.org/api v0.162.0 h1:Vhs54HkaEpkMBdgGdOT2P6F0csGG/vxDS0hWHJzmmps=
google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= google.golang.org/api v0.162.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYlAHs0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -1885,12 +1923,12 @@ google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqw
google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY=
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917/go.mod h1:pZqR+glSb11aJ+JQcczCvgf47+duRuzNSKqE8YAQnV0= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo=
google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 h1:s1w3X6gQxwrLEpxnLd/qXTVLgQE2yXwaOaoa6IlY/+o= google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0=
google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0/go.mod h1:CAny0tYF+0/9rmDB9fahA9YLzX3+AEVl1qXbv5hhj6c= google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 h1:gphdwh0npgs8elJ4T6J+DQJHPVF7RsuJHCfwztUb4J4= google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
@ -1932,8 +1970,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@ -1950,8 +1988,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -1,52 +0,0 @@
run:
tests: false
# # timeout for analysis, e.g. 30s, 5m, default is 1m
# timeout: 5m
linters:
disable-all: true
enable:
- bodyclose
- deadcode
- depguard
- dogsled
# - errcheck
- goconst
- gocritic
- gofmt
- goimports
- golint
- gosec
- gosimple
- govet
- ineffassign
- interfacer
- maligned
- misspell
- nakedret
- prealloc
- scopelint
- staticcheck
- structcheck
- stylecheck
- typecheck
- unconvert
- unused
- misspell
- wsl
issues:
exclude-rules:
- text: "Use of weak random number generator"
linters:
- gosec
- text: "comment on exported var"
linters:
- golint
linters-settings:
dogsled:
max-blank-identifiers: 3
maligned:
# print struct with more effective memory layout or not, false by default
suggest-new: true

View File

@ -0,0 +1,42 @@
syntax = "proto3";
package zgc.precisebank.v1;
import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
option go_package = "github.com/0glabs/0g-chain/x/precisebank/types";
// GenesisState defines the precisebank module's genesis state.
message GenesisState {
// balances is a list of all the balances in the precisebank module.
repeated FractionalBalance balances = 1 [
(gogoproto.castrepeated) = "FractionalBalances",
(gogoproto.nullable) = false
];
// remainder is an internal value of how much extra fractional digits are
// still backed by the reserve, but not assigned to any account.
string remainder = 2 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];
}
// FractionalBalance defines the fractional portion of an account balance
message FractionalBalance {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
// address is the address of the balance holder.
string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
// amount indicates amount of only the fractional balance owned by the
// address. FractionalBalance currently only supports tracking 1 single asset,
// e.g. fractional balances of ukava.
string amount = 2 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];
}

View File

@ -0,0 +1,62 @@
syntax = "proto3";
package zgc.precisebank.v1;
import "cosmos/base/v1beta1/coin.proto";
import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
option go_package = "github.com/0glabs/0g-chain/x/precisebank/types";
option (gogoproto.goproto_getters_all) = false;
// Query defines the gRPC querier service for precisebank module
service Query {
// TotalFractionalBalances returns the total sum of all fractional balances
// managed by the precisebank module.
rpc TotalFractionalBalances(QueryTotalFractionalBalancesRequest) returns (QueryTotalFractionalBalancesResponse) {
option (google.api.http).get = "/0g/precisebank/v1/total_fractional_balances";
}
// Remainder returns the amount backed by the reserve, but not yet owned by
// any account, i.e. not in circulation.
rpc Remainder(QueryRemainderRequest) returns (QueryRemainderResponse) {
option (google.api.http).get = "/0g/precisebank/v1/remainder";
}
// FractionalBalance returns only the fractional balance of an address. This
// does not include any integer balance.
rpc FractionalBalance(QueryFractionalBalanceRequest) returns (QueryFractionalBalanceResponse) {
option (google.api.http).get = "/0g/precisebank/v1/fractional_balance/{address}";
}
}
// QueryTotalFractionalBalancesRequest defines the request type for Query/TotalFractionalBalances method.
message QueryTotalFractionalBalancesRequest {}
// QueryTotalFractionalBalancesResponse defines the response type for Query/TotalFractionalBalances method.
message QueryTotalFractionalBalancesResponse {
// total is the total sum of all fractional balances managed by the precisebank
// module.
cosmos.base.v1beta1.Coin total = 1 [(gogoproto.nullable) = false];
}
// QueryRemainderRequest defines the request type for Query/Remainder method.
message QueryRemainderRequest {}
// QueryRemainderResponse defines the response type for Query/Remainder method.
message QueryRemainderResponse {
// remainder is the amount backed by the reserve, but not yet owned by any
// account, i.e. not in circulation.
cosmos.base.v1beta1.Coin remainder = 1 [(gogoproto.nullable) = false];
}
// QueryFractionalBalanceRequest defines the request type for Query/FractionalBalance method.
message QueryFractionalBalanceRequest {
// address is the account address to query fractional balance for.
string address = 1;
}
// QueryFractionalBalanceResponse defines the response type for Query/FractionalBalance method.
message QueryFractionalBalanceResponse {
// fractional_balance is the fractional balance of the address.
cosmos.base.v1beta1.Coin fractional_balance = 1 [(gogoproto.nullable) = false];
}

View File

@ -0,0 +1,52 @@
package main
import (
"os"
"github.com/strangelove-ventures/interchaintest/v7/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v7/ibc"
"github.com/strangelove-ventures/interchaintest/v7/testutil"
)
const (
KavaTestChainId = "kava_8888-1"
KavaEvmTestChainId = int64(8888)
)
func DefaultKavaChainConfig(chainId string) ibc.ChainConfig {
kavaImageTag := os.Getenv("KAVA_TAG")
if kavaImageTag == "" {
kavaImageTag = "v0.26.0-rocksdb"
}
// app.toml overrides
jsonRpcOverrides := make(testutil.Toml)
jsonRpcOverrides["address"] = "0.0.0.0:8545"
appTomlOverrides := make(testutil.Toml)
appTomlOverrides["json-rpc"] = jsonRpcOverrides
// genesis param overrides
genesis := []cosmos.GenesisKV{
cosmos.NewGenesisKV("consensus_params.block.max_gas", "20000000"),
cosmos.NewGenesisKV("app_state.evm.params.evm_denom", "akava"),
// update for fast voting periods
cosmos.NewGenesisKV("app_state.gov.params.voting_period", "10s"),
cosmos.NewGenesisKV("app_state.gov.params.min_deposit.0.denom", "ukava"),
}
return ibc.ChainConfig{
Type: "cosmos",
ChainID: chainId,
Images: []ibc.DockerImage{{Repository: "kava/kava", Version: kavaImageTag, UidGid: "0:0"}},
// Images: []ibc.DockerImage{{Repository: "ghcr.io/strangelove-ventures/heighliner/kava", Version: "v0.26.0", UidGid: "1025:1025"}},
Bin: "kava",
Bech32Prefix: "kava",
Denom: "ukava",
GasPrices: "0ukava", // 0 gas price makes calculating expected balances simpler
GasAdjustment: 1.5,
TrustingPeriod: "168h0m0s",
ModifyGenesis: cosmos.ModifyGenesis(genesis),
ExposeAdditionalPorts: []string{"8545/tcp"},
ConfigFileOverrides: map[string]any{"config/app.toml": appTomlOverrides},
}
}

View File

@ -0,0 +1,59 @@
package main_test
import (
"context"
"fmt"
"testing"
"time"
"go.uber.org/zap/zaptest"
"github.com/strangelove-ventures/interchaintest/v7"
"github.com/strangelove-ventures/interchaintest/v7/conformance"
"github.com/strangelove-ventures/interchaintest/v7/ibc"
"github.com/strangelove-ventures/interchaintest/v7/testreporter"
"github.com/stretchr/testify/require"
kavainterchain "github.com/kava-labs/kava/tests/interchain"
)
var (
numFullNodes = 0
numValidators = 1
)
func TestIbcConformance(t *testing.T) {
// t.Skip("skipping conformance test")
ctx := context.Background()
// setup chain factories: must be exactly two chains to run conformance between
cfs := make([]interchaintest.ChainFactory, 0)
cfs = append(cfs,
interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
{
Name: "kava",
ChainConfig: kavainterchain.DefaultKavaChainConfig(kavainterchain.KavaTestChainId),
// override default number of nodes to limit the number of ports we need to bind to
// running conformance tests without these limits result in errors that look like
// tendermint rpc client status: post failed: Post "http://127.0.0.1:<port>": dial tcp 127.0.0.1:<port>: connect: can't assign requested address
NumValidators: &numValidators,
NumFullNodes: &numFullNodes,
},
{Name: "osmosis", Version: "v24.0.1", NumValidators: &numValidators, NumFullNodes: &numFullNodes},
}),
)
// setup relayer factory
rfs := make([]interchaintest.RelayerFactory, 0)
rfs = append(rfs,
interchaintest.NewBuiltinRelayerFactory(ibc.CosmosRly, zaptest.NewLogger(t)),
)
// test reporter
f, err := interchaintest.CreateLogFile(fmt.Sprintf("%d.json", time.Now().Unix()))
require.NoError(t, err)
rep := testreporter.NewReporter(f)
conformance.Test(t, ctx, cfs, rfs, rep)
}

290
tests/e2e-ibc/erc20_test.go Normal file
View File

@ -0,0 +1,290 @@
package main_test
import (
"context"
"crypto/sha256"
"encoding/json"
"fmt"
"math/big"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
gov1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
paramsutils "github.com/cosmos/cosmos-sdk/x/params/client/utils"
transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/strangelove-ventures/interchaintest/v7"
"github.com/strangelove-ventures/interchaintest/v7/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v7/ibc"
"github.com/strangelove-ventures/interchaintest/v7/testreporter"
"github.com/0glabs/0g-chain/app"
"github.com/0glabs/0g-chain/client/erc20"
"github.com/0glabs/0g-chain/tests/e2e/runner"
"github.com/0glabs/0g-chain/tests/e2e/testutil"
kavainterchain "github.com/0glabs/0g-chain/tests/interchain"
"github.com/0glabs/0g-chain/tests/util"
evmutiltypes "github.com/0glabs/0g-chain/x/evmutil/types"
)
// This test does the following:
// - set up a network with kava & cosmoshub w/ IBC channels between them
// - deploy an ERC20 to Kava EVM
// - configure Kava to support conversion of ERC20 to Cosmos Coin
// - IBC the sdk.Coin representation of the ERC20 to cosmoshub
func TestInterchainErc20(t *testing.T) {
app.SetSDKConfig()
ctx := context.Background()
// Configure & run chains with interchaintest
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
{Name: "kava", ChainConfig: kavainterchain.DefaultKavaChainConfig(kavainterchain.KavaTestChainId)},
{Name: "gaia", Version: "v15.2.0", ChainConfig: ibc.ChainConfig{GasPrices: "0.0uatom"}},
})
chains, err := cf.Chains(t.Name())
require.NoError(t, err)
ictKava := chains[0].(*cosmos.CosmosChain)
gaia := chains[1].(*cosmos.CosmosChain)
client, network := interchaintest.DockerSetup(t)
r := interchaintest.NewBuiltinRelayerFactory(ibc.CosmosRly, zaptest.NewLogger(t)).
Build(t, client, network)
// configure interchain
const kavaGaiaIbcPath = "kava-gaia-ibc"
ic := interchaintest.NewInterchain().AddChain(ictKava).
AddChain(gaia).
AddRelayer(r, "relayer").
AddLink(interchaintest.InterchainLink{
Chain1: ictKava,
Chain2: gaia,
Relayer: r,
Path: kavaGaiaIbcPath,
})
// Log location
f, err := interchaintest.CreateLogFile(fmt.Sprintf("%d.json", time.Now().Unix()))
require.NoError(t, err)
// Reporter/logs
rep := testreporter.NewReporter(f)
eRep := rep.RelayerExecReporter(t)
// Build interchain
err = ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{
TestName: t.Name(),
Client: client,
NetworkID: network,
SkipPathCreation: false},
)
require.NoError(t, err)
// Create and Fund User Wallets
fundAmount := math.NewInt(1e12)
users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), fundAmount, ictKava, gaia)
kavaUser := users[0]
gaiaUser := users[1]
// wait for new block to ensure initial funding complete
height, err := ictKava.Height(ctx)
require.NoError(t, err)
h := height
for h <= height {
h, err = ictKava.Height(ctx)
require.NoError(t, err)
}
gaiaChannelInfo, err := r.GetChannels(ctx, eRep, gaia.Config().ChainID)
require.NoError(t, err)
gaiaToKavaChannelID := gaiaChannelInfo[0].ChannelID
kavaToGaiaChannelID := gaiaChannelInfo[0].Counterparty.ChannelID
// for simplified management of the chain, use kava's e2e framework for account management
// this skirts problems in interchaintest with needing coin type 60
// there are exceptions in the relayer & ibc channel management that complicate setting the chain
// default coin type to 60 in the chain config.
// we need to fund an account and then all of kava's e2e testutil chain management will work.
rpcUrl, err := ictKava.FullNodes[0].GetHostAddress(ctx, "26657/tcp")
require.NoError(t, err, "failed to find rpc URL")
grpcUrl, err := ictKava.FullNodes[0].GetHostAddress(ctx, "9090/tcp")
require.NoError(t, err, "failed to find grpc URL")
evmUrl, err := ictKava.FullNodes[0].GetHostAddress(ctx, "8545/tcp")
require.NoError(t, err, "failed to find evm URL")
evmClient, err := ethclient.Dial(evmUrl)
require.NoError(t, err, "failed to connect to evm")
// create a funded evm account to initialize the testutil.Chain
// use testutil.Chain for account management because the accounts play nicely with EVM & SDK sides
deployerMnemonic, err := util.RandomMnemonic()
require.NoError(t, err)
evmDeployer, err := util.NewEvmSignerFromMnemonic(evmClient, big.NewInt(kavainterchain.KavaEvmTestChainId), deployerMnemonic)
require.NoError(t, err)
deployerKavaAddr := util.EvmToSdkAddress(evmDeployer.Address())
err = ictKava.SendFunds(ctx, kavaUser.KeyName(), ibc.WalletAmount{
Address: deployerKavaAddr.String(),
Denom: "ukava",
Amount: math.NewInt(1e10),
})
require.NoError(t, err)
// initialize testutil.Chain for account & tx management on both sdk & evm
kava, err := testutil.NewChain(t, &runner.ChainDetails{
RpcUrl: rpcUrl,
GrpcUrl: grpcUrl,
EvmRpcUrl: evmUrl,
ChainId: kavainterchain.KavaTestChainId,
StakingDenom: "ukava",
}, deployerMnemonic)
require.NoError(t, err)
deployer := kava.GetAccount("whale")
// deploy ERC20 contract
usdtAddr, deployTx, usdt, err := erc20.DeployErc20(
deployer.EvmAuth, kava.EvmClient,
"Test Tether USD", "USDT", 6,
)
require.NoError(t, err)
require.NotNil(t, usdtAddr)
require.NotNil(t, usdt)
_, err = util.WaitForEvmTxReceipt(kava.EvmClient, deployTx.Hash(), 10*time.Second)
require.NoError(t, err)
////////////////////////////////////////////
// enable conversion from erc20 -> sdk.Coin
// (assumes there are none pre-configured!)
////////////////////////////////////////////
// 1. Submit Proposal
sdkDenom := "tether/usdt"
rawCps, err := json.Marshal(evmutiltypes.NewConversionPairs(
evmutiltypes.NewConversionPair(
evmutiltypes.NewInternalEVMAddress(usdtAddr),
sdkDenom,
),
))
require.NoError(t, err)
paramChange := paramsutils.ParamChangeProposalJSON{
Title: "Enable erc20 conversion to sdk.Coin",
Description: ".",
Changes: paramsutils.ParamChangesJSON{
paramsutils.ParamChangeJSON{
Subspace: "evmutil",
Key: "EnabledConversionPairs",
Value: rawCps,
},
},
Deposit: "10000000ukava",
}
_, err = legacyParamChangeProposal(ictKava.FullNodes[0], ctx, kavaUser.KeyName(), &paramChange)
require.NoError(t, err, "error submitting param change proposal tx")
// TODO: query proposal id. assuming it is 1 here.
propId := int64(1)
// 2. Vote on Proposal
err = ictKava.VoteOnProposalAllValidators(ctx, propId, cosmos.ProposalVoteYes)
require.NoError(t, err, "failed to submit votes")
height, _ = ictKava.Height(ctx)
_, err = cosmos.PollForProposalStatus(ctx, ictKava, height, height+10, propId, gov1beta1.StatusPassed)
require.NoError(t, err, "proposal status did not change to passed in expected number of blocks")
// fund a user & mint them some usdt
user := kava.NewFundedAccount("tether-user", sdk.NewCoins(sdk.NewCoin("ukava", math.NewInt(1e7))))
erc20FundAmt := big.NewInt(100e6)
mintTx, err := usdt.Mint(deployer.EvmAuth, user.EvmAddress, erc20FundAmt)
require.NoError(t, err)
_, err = util.WaitForEvmTxReceipt(kava.EvmClient, mintTx.Hash(), 10*time.Second)
require.NoError(t, err)
// verify they have erc20 balance!
bal, err := usdt.BalanceOf(nil, user.EvmAddress)
require.NoError(t, err)
require.Equal(t, erc20FundAmt, bal)
// convert the erc20 to sdk.Coin!
amountToConvert := math.NewInt(50e6)
msg := evmutiltypes.NewMsgConvertERC20ToCoin(
evmutiltypes.NewInternalEVMAddress(user.EvmAddress),
user.SdkAddress,
evmutiltypes.NewInternalEVMAddress(usdtAddr),
amountToConvert,
)
convertTx := util.KavaMsgRequest{
Msgs: []sdk.Msg{&msg},
GasLimit: 4e5,
FeeAmount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(400))),
Data: "converting sdk coin to erc20",
}
res := user.SignAndBroadcastKavaTx(convertTx)
require.NoError(t, res.Err)
// check balance of cosmos coin!
sdkBalance := kava.QuerySdkForBalances(user.SdkAddress)
require.Equal(t, amountToConvert, sdkBalance.AmountOf(sdkDenom))
// IBC the newly minted sdk.Coin to gaia
dstAddress := gaiaUser.FormattedAddress()
transfer := ibc.WalletAmount{
Address: dstAddress,
Denom: ictKava.Config().Denom,
Amount: amountToConvert,
}
_, err = ictKava.SendIBCTransfer(ctx, kavaToGaiaChannelID, kavaUser.KeyName(), transfer, ibc.TransferOptions{})
require.NoError(t, err)
// manually flush packets so we don't need to wait for the relayer
require.NoError(t, r.Flush(ctx, eRep, kavaGaiaIbcPath, kavaToGaiaChannelID))
// determine IBC denom & check gaia balance
srcDenomTrace := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", gaiaToKavaChannelID, ictKava.Config().Denom))
erc20OnGaiaDenom := srcDenomTrace.IBCDenom()
gaiaBal, err := gaia.GetBalance(ctx, dstAddress, erc20OnGaiaDenom)
require.NoError(t, err)
require.Equal(t, amountToConvert, gaiaBal)
}
// copied from https://github.com/strangelove-ventures/interchaintest/blob/7272afc780da6e2c99b2d2b3d084d5a3b1c6895f/chain/cosmos/chain_node.go#L1292
// but changed "submit-proposal" to "submit-legacy-proposal"
func legacyParamChangeProposal(tn *cosmos.ChainNode, ctx context.Context, keyName string, prop *paramsutils.ParamChangeProposalJSON) (string, error) {
content, err := json.Marshal(prop)
if err != nil {
return "", err
}
hash := sha256.Sum256(content)
proposalFilename := fmt.Sprintf("%x.json", hash)
err = tn.WriteFile(ctx, content, proposalFilename)
if err != nil {
return "", fmt.Errorf("writing param change proposal: %w", err)
}
proposalPath := filepath.Join(tn.HomeDir(), proposalFilename)
command := []string{
"gov", "submit-legacy-proposal",
"param-change",
proposalPath,
}
return tn.ExecTx(ctx, keyName, command...)
}

297
tests/e2e-ibc/go.mod Normal file
View File

@ -0,0 +1,297 @@
module github.com/kava-labs/kava/tests/interchain
go 1.21.9
require (
cosmossdk.io/math v1.3.0
github.com/cosmos/ibc-go/v7 v7.4.0
github.com/ethereum/go-ethereum v1.10.26
github.com/stretchr/testify v1.9.0
go.uber.org/zap v1.26.0
)
require (
github.com/cosmos/cosmos-sdk v0.47.10
github.com/kava-labs/kava v0.0.0-00010101000000-000000000000
github.com/strangelove-ventures/interchaintest/v7 v7.0.1-0.20240506191732-71a15c29f2b7
)
require (
cloud.google.com/go v0.112.0 // indirect
cloud.google.com/go/compute v1.24.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v1.1.6 // indirect
cloud.google.com/go/storage v1.36.0 // indirect
cosmossdk.io/api v0.3.1 // indirect
cosmossdk.io/core v0.6.1 // indirect
cosmossdk.io/depinject v1.0.0-alpha.4 // indirect
cosmossdk.io/errors v1.0.1 // indirect
cosmossdk.io/log v1.3.1 // indirect
cosmossdk.io/tools/rosetta v0.2.1 // indirect
filippo.io/edwards25519 v1.0.0 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/99designs/keyring v1.2.2 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect
github.com/DataDog/zstd v1.5.5 // indirect
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/StirlingMarketingGroup/go-namecase v1.0.0 // indirect
github.com/VictoriaMetrics/fastcache v1.12.1 // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/avast/retry-go/v4 v4.5.0 // indirect
github.com/aws/aws-sdk-go v1.44.203 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect
github.com/btcsuite/btcd v0.24.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
github.com/btcsuite/btcd/btcutil v1.1.5 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/chzyer/readline v1.5.1 // indirect
github.com/cockroachdb/errors v1.11.1 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/pebble v1.1.0 // indirect
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/coinbase/rosetta-sdk-go/types v1.0.0 // indirect
github.com/cometbft/cometbft v0.37.9 // indirect
github.com/cometbft/cometbft-db v0.9.1 // indirect
github.com/confio/ics23/go v0.9.0 // indirect
github.com/cosmos/btcutil v1.0.5 // indirect
github.com/cosmos/cosmos-db v1.0.2 // indirect
github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect
github.com/cosmos/go-bip39 v1.0.0 // indirect
github.com/cosmos/gogogateway v1.2.0 // indirect
github.com/cosmos/gogoproto v1.4.10 // indirect
github.com/cosmos/iavl v1.2.0 // indirect
github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3 // indirect
github.com/cosmos/ibc-go/modules/capability v1.0.0-rc1 // indirect
github.com/cosmos/ics23/go v0.10.0 // indirect
github.com/cosmos/interchain-security/v3 v3.1.1-0.20231102122221-81650a84f989 // indirect
github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect
github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect
github.com/creachadair/taskgroup v0.4.2 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/base58 v1.0.4 // indirect
github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/docker v24.0.7+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dvsekhvalnov/jose2go v1.6.0 // indirect
github.com/edsrzf/mmap-go v1.0.0 // indirect
github.com/emicklei/dot v1.6.1 // indirect
github.com/evmos/ethermint v0.21.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
github.com/getsentry/sentry-go v0.27.0 // indirect
github.com/go-kit/kit v0.13.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/gogo/googleapis v1.4.1 // indirect
github.com/gogo/protobuf v1.3.3 // indirect
github.com/golang/glog v1.2.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/orderedcode v0.0.1 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/gorilla/handlers v1.5.1 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
github.com/gtank/merlin v0.1.1 // indirect
github.com/gtank/ristretto255 v0.1.2 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-getter v1.7.5 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hdevalence/ed25519consensus v0.1.0 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/holiman/uint256 v1.2.4 // indirect
github.com/huandu/skiplist v1.2.0 // indirect
github.com/huin/goupnp v1.3.0 // indirect
github.com/iancoleman/orderedmap v0.2.0 // indirect
github.com/icza/dyno v0.0.0-20220812133438-f0b6f8a18845 // indirect
github.com/improbable-eng/grpc-web v0.15.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/ipfs/go-cid v0.4.1 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/klauspost/compress v1.17.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/lib/pq v1.10.7 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-libp2p v0.27.8 // indirect
github.com/linxGnu/grocksdb v1.8.13 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/manifoldco/promptui v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b // indirect
github.com/minio/highwayhash v1.0.2 // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/misko9/go-substrate-rpc-client/v4 v4.0.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/mtibben/percent v0.2.1 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
github.com/multiformats/go-multiaddr v0.9.0 // indirect
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.8.1 // indirect
github.com/multiformats/go-multihash v0.2.1 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc2 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67 // indirect
github.com/pierrec/xxHash v0.1.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.17.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.13.0 // indirect
github.com/prometheus/tsdb v0.7.1 // indirect
github.com/rakyll/statik v0.1.7 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/rjeczalik/notify v0.9.1 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/rs/cors v1.8.3 // indirect
github.com/rs/zerolog v1.32.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sasha-s/go-deadlock v0.3.1 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/cobra v1.8.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.18.2 // indirect
github.com/status-im/keycard-go v0.2.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
github.com/tendermint/go-amino v0.16.0 // indirect
github.com/tidwall/btree v1.7.0 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/tyler-smith/go-bip32 v1.0.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/ulikunitz/xz v0.5.11 // indirect
github.com/vedhavyas/go-subkey/v2 v2.0.0 // indirect
github.com/zondax/hid v0.9.2 // indirect
github.com/zondax/ledger-go v0.14.3 // indirect
go.etcd.io/bbolt v1.3.8 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect
go.opentelemetry.io/otel v1.22.0 // indirect
go.opentelemetry.io/otel/metric v1.22.0 // indirect
go.opentelemetry.io/otel/trace v1.22.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/oauth2 v0.17.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/term v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.20.0 // indirect
google.golang.org/api v0.162.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect
google.golang.org/grpc v1.63.2 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.1.7 // indirect
lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/cc/v3 v3.40.0 // indirect
modernc.org/ccgo/v3 v3.16.13 // indirect
modernc.org/libc v1.24.1 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.6.0 // indirect
modernc.org/opt v0.1.3 // indirect
modernc.org/sqlite v1.25.0 // indirect
modernc.org/strutil v1.1.3 // indirect
modernc.org/token v1.0.1 // indirect
nhooyr.io/websocket v1.8.7 // indirect
pgregory.net/rapid v1.1.0 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)
replace (
// use cosmos fork of keyring
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
// Use cometbft fork of tendermint
github.com/cometbft/cometbft => github.com/kava-labs/cometbft v0.37.9-kava.1
github.com/cometbft/cometbft-db => github.com/kava-labs/cometbft-db v0.9.1-kava.2
// Use cosmos-sdk fork with backported fix for unsafe-reset-all, staking transfer events, and custom tally handler support
github.com/cosmos/cosmos-sdk => github.com/kava-labs/cosmos-sdk v0.47.10-iavl-v1-kava.1
github.com/ethereum/go-ethereum => github.com/Kava-Labs/go-ethereum v1.10.27-0.20240308170502-da7973e5eee0
// Use ethermint fork that respects min-gas-price with NoBaseFee true and london enabled, and includes eip712 support
github.com/evmos/ethermint => github.com/kava-labs/ethermint v0.21.1-0.20240703152838-badab86e5aba
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
// github.com/ComposableFi/go-subkey/v2 => github.com/vedhavyas/go-subkey/v2 v2.0.0
github.com/misko9/go-substrate-rpc-client/v4 => github.com/faddat/go-substrate-rpc-client/v4 v4.0.1-0.20240402155230-48db8c110afe
// stick with compatible version or x/exp in v0.47.x line
golang.org/x/exp => golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb
)
replace github.com/kava-labs/kava => ../../

1942
tests/e2e-ibc/go.sum Normal file

File diff suppressed because it is too large Load Diff

206
tests/e2e-ibc/main_test.go Normal file
View File

@ -0,0 +1,206 @@
package main_test
import (
"context"
"fmt"
"testing"
"time"
"cosmossdk.io/math"
transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/strangelove-ventures/interchaintest/v7"
"github.com/strangelove-ventures/interchaintest/v7/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v7/ibc"
"github.com/strangelove-ventures/interchaintest/v7/testreporter"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
kavainterchain "github.com/kava-labs/kava/tests/interchain"
)
func TestInterchainIBC(t *testing.T) {
ctx := context.Background()
// setup chains
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
{Name: "kava", ChainConfig: kavainterchain.DefaultKavaChainConfig(kavainterchain.KavaTestChainId)},
{Name: "gaia", Version: "v15.2.0", ChainConfig: ibc.ChainConfig{GasPrices: "0.0uatom"}},
{Name: "osmosis", Version: "v24.0.1"},
})
chains, err := cf.Chains(t.Name())
require.NoError(t, err)
kava, gaia, osmosis := chains[0].(*cosmos.CosmosChain), chains[1].(*cosmos.CosmosChain), chains[2].(*cosmos.CosmosChain)
// setup relayer
client, network := interchaintest.DockerSetup(t)
r := interchaintest.NewBuiltinRelayerFactory(ibc.CosmosRly, zaptest.NewLogger(t)).
Build(t, client, network)
// configure interchain
const kavaGaiaIbcPath = "kava-gaia-demo"
const kavaOsmosisIbcPath = "kava-osmo-demo"
ic := interchaintest.NewInterchain().
AddChain(kava).
AddChain(gaia).
AddChain(osmosis).
AddRelayer(r, "relayer").
AddLink(interchaintest.InterchainLink{
Chain1: kava,
Chain2: gaia,
Relayer: r,
Path: kavaGaiaIbcPath,
}).
AddLink(interchaintest.InterchainLink{
Chain1: kava,
Chain2: osmosis,
Relayer: r,
Path: kavaOsmosisIbcPath,
})
// Log location
f, err := interchaintest.CreateLogFile(fmt.Sprintf("%d.json", time.Now().Unix()))
require.NoError(t, err)
// Reporter/logs
rep := testreporter.NewReporter(f)
eRep := rep.RelayerExecReporter(t)
// Build interchain
err = ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{
TestName: t.Name(),
Client: client,
NetworkID: network,
SkipPathCreation: false},
)
require.NoError(t, err)
// start the relayer so we don't need to manually Flush() packets
err = r.StartRelayer(ctx, eRep, kavaGaiaIbcPath, kavaOsmosisIbcPath)
require.NoError(t, err)
defer r.StopRelayer(ctx, eRep)
// Create and Fund User Wallets
fundAmount := math.NewInt(10_000_000)
users := interchaintest.GetAndFundTestUsers(t, ctx, "default", fundAmount, kava, gaia, osmosis)
kavaUser := users[0]
gaiaUser := users[1]
osmosisUser := users[2]
// wait for new block to ensure initial funding complete
height, err := kava.Height(ctx)
require.NoError(t, err)
h := height
for h <= height {
h, err = kava.Height(ctx)
require.NoError(t, err)
}
// check initial balance
kavaUserBalInitial, err := kava.GetBalance(ctx, kavaUser.FormattedAddress(), kava.Config().Denom)
require.NoError(t, err)
require.True(t, kavaUserBalInitial.Equal(fundAmount))
// get ibc channel ids
gaiaChannelInfo, err := r.GetChannels(ctx, eRep, gaia.Config().ChainID)
require.NoError(t, err)
osmoChannelInfo, err := r.GetChannels(ctx, eRep, osmosis.Config().ChainID)
require.NoError(t, err)
gaiaToKavaChannelID := gaiaChannelInfo[0].ChannelID
kavaToGaiaChannelID := gaiaChannelInfo[0].Counterparty.ChannelID
osmoToKavaChannelID := osmoChannelInfo[0].ChannelID
kavaToOsmoChannelID := osmoChannelInfo[0].Counterparty.ChannelID
// determine ibc denoms
srcDenomTrace := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", gaiaToKavaChannelID, kava.Config().Denom))
kavaOnGaiaDenom := srcDenomTrace.IBCDenom()
srcDenomTrace = transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", osmoToKavaChannelID, kava.Config().Denom))
kavaOnOsmoDenom := srcDenomTrace.IBCDenom()
amountToSend := math.NewInt(1_000_000)
// IBC transfer kava to cosmoshub
// inspired by https://github.com/strangelove-ventures/interchaintest/blob/main/examples/ibc/learn_ibc_test.go
t.Run("ibc transfer kava -> cosmoshub", func(t *testing.T) {
dstAddress := gaiaUser.FormattedAddress()
transfer := ibc.WalletAmount{
Address: dstAddress,
Denom: kava.Config().Denom,
Amount: amountToSend,
}
tx, err := kava.SendIBCTransfer(ctx, kavaToGaiaChannelID, kavaUser.KeyName(), transfer, ibc.TransferOptions{})
require.NoError(t, err)
require.NoError(t, tx.Validate())
// manually flush packets so we don't need to wait for the relayer
require.NoError(t, r.Flush(ctx, eRep, kavaGaiaIbcPath, kavaToGaiaChannelID))
// verify balance deducted from kava account
expectedBal := kavaUserBalInitial.Sub(amountToSend)
kavaUserBalNew, err := kava.GetBalance(ctx, kavaUser.FormattedAddress(), kava.Config().Denom)
require.NoError(t, err)
require.True(t, kavaUserBalNew.Equal(expectedBal))
// verify cosmoshub account received funds
gaiaUserBalNew, err := gaia.GetBalance(ctx, gaiaUser.FormattedAddress(), kavaOnGaiaDenom)
require.NoError(t, err)
require.True(t, gaiaUserBalNew.Equal(amountToSend))
})
// use coins IBC'd to cosmoshub, send them to osmosis using pfm
t.Run("packet forwarding middleware: cosmoshub -> kava -> osmosis", func(t *testing.T) {
dstAddress := osmosisUser.FormattedAddress()
transfer := ibc.WalletAmount{
Address: "pfm", // purposefully invalid b/c we are forwarding through kava onward to osmosis!
Denom: kavaOnGaiaDenom,
Amount: amountToSend,
}
tx, err := gaia.SendIBCTransfer(ctx, gaiaToKavaChannelID, gaiaUser.KeyName(), transfer, ibc.TransferOptions{
// packet forwarding middleware!
Memo: fmt.Sprintf(`{
"forward": {
"receiver": "%s",
"port": "transfer",
"channel": "%s"
}
}`, dstAddress, kavaToOsmoChannelID),
})
require.NoError(t, err)
require.NoError(t, tx.Validate())
require.Eventually(t, func() bool {
// verify transfer to osmosis
osmosisUserBalNew, err := osmosis.GetBalance(ctx, osmosisUser.FormattedAddress(), kavaOnOsmoDenom)
require.NoError(t, err)
return osmosisUserBalNew.Equal(amountToSend)
}, 15*time.Second, time.Second, "osmosis never received funds")
// verify cosmoshub account no longer has the funds
gaiaUserBalNew, err := gaia.GetBalance(ctx, gaiaUser.FormattedAddress(), kavaOnGaiaDenom)
require.NoError(t, err)
require.True(t, gaiaUserBalNew.Equal(math.ZeroInt()))
})
t.Run("query evm data", func(t *testing.T) {
evmUrl, err := kava.FullNodes[0].GetHostAddress(ctx, "8545/tcp")
require.NoError(t, err)
evmClient, err := ethclient.Dial(evmUrl)
require.NoError(t, err, "failed to connect to evm")
bal, err := evmClient.BalanceAt(ctx, common.BytesToAddress(kavaUser.Address()), nil)
require.NoError(t, err)
// convert ukava to akava
expected := fundAmount.Sub(amountToSend).MulRaw(1e12)
require.Equal(t, expected.BigInt().String(), bal.String())
})
}

View File

@ -21,12 +21,12 @@ E2E_SKIP_SHUTDOWN=false
# E2E_INCLUDE_AUTOMATED_UPGRADE when true enables the automated upgrade & corresponding tests in the suite. # E2E_INCLUDE_AUTOMATED_UPGRADE when true enables the automated upgrade & corresponding tests in the suite.
E2E_INCLUDE_AUTOMATED_UPGRADE=true E2E_INCLUDE_AUTOMATED_UPGRADE=true
# E2E_KAVA_UPGRADE_NAME is the name of the upgrade that must be in the current local image. # E2E_KAVA_UPGRADE_NAME is the name of the upgrade that must be in the current local image.
E2E_KAVA_UPGRADE_NAME=v0.26.0 E2E_KAVA_UPGRADE_NAME=v0.27.0
# E2E_KAVA_UPGRADE_HEIGHT is the height at which the upgrade will be applied. # E2E_KAVA_UPGRADE_HEIGHT is the height at which the upgrade will be applied.
# If IBC tests are enabled this should be >30. Otherwise, this should be >10. # If IBC tests are enabled this should be >30. Otherwise, this should be >10.
E2E_KAVA_UPGRADE_HEIGHT=35 E2E_KAVA_UPGRADE_HEIGHT=35
# E2E_KAVA_UPGRADE_BASE_IMAGE_TAG is the tag of the docker image the chain should upgrade from. # E2E_KAVA_UPGRADE_BASE_IMAGE_TAG is the tag of the docker image the chain should upgrade from.
E2E_KAVA_UPGRADE_BASE_IMAGE_TAG=v0.25.1-goleveldb E2E_KAVA_UPGRADE_BASE_IMAGE_TAG=v0.26.0-goleveldb
# E2E_KAVA_ERC20_ADDRESS is the address of a pre-deployed ERC20 token with the following properties: # E2E_KAVA_ERC20_ADDRESS is the address of a pre-deployed ERC20 token with the following properties:
# - the E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC has nonzero balance # - the E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC has nonzero balance

View File

@ -1,127 +1,102 @@
package e2e_test package e2e_test
import ( import (
"time" precisebanktypes "github.com/0glabs/0g-chain/x/precisebank/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
tmtypes "github.com/cometbft/cometbft/types"
sdk "github.com/cosmos/cosmos-sdk/types"
consensustypes "github.com/cosmos/cosmos-sdk/x/consensus/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
) )
func (suite *IntegrationTestSuite) TestUpgradeParams_SDK() { func (suite *IntegrationTestSuite) TestUpgrade_PreciseBankReserveTransfer() {
suite.SkipIfUpgradeDisabled() suite.SkipIfUpgradeDisabled()
beforeUpgradeCtx := suite.ZgChain.Grpc.CtxAtHeight(suite.UpgradeHeight - 1) // beforeUpgradeCtx := suite.Kava.Grpc.CtxAtHeight(suite.UpgradeHeight - 1)
afterUpgradeCtx := suite.ZgChain.Grpc.CtxAtHeight(suite.UpgradeHeight) // afterUpgradeCtx := suite.Kava.Grpc.CtxAtHeight(suite.UpgradeHeight)
// Before params // grpcClient := suite.Kava.Grpc
grpcClient := suite.ZgChain.Grpc
govParamsBefore, err := grpcClient.Query.Gov.Params(beforeUpgradeCtx, &govtypes.QueryParamsRequest{
ParamsType: govtypes.ParamDeposit,
})
suite.NoError(err)
govParamsAfter, err := grpcClient.Query.Gov.Params(afterUpgradeCtx, &govtypes.QueryParamsRequest{
ParamsType: govtypes.ParamDeposit,
})
suite.NoError(err)
// after upgrade, querying params before upgrade height returns nil // -----------------------------
// since the param gprc query no longer queries x/params // Get initial reserve balances
suite.Run("x/gov parameters before upgrade", func() { evmutilAddr := "kava1w9vxuke5dz6hyza2j932qgmxltnfxwl78u920k"
suite.Assert().Nil( precisebankAddr := "kava12yfe2jaupmtjruwxsec7hg7er60fhaa4uz7ffl"
govParamsBefore.DepositParams.MaxDepositPeriod,
"x/gov DepositParams max deposit period before upgrade should be nil",
)
suite.Assert().Nil(
govParamsBefore.DepositParams.MinDeposit,
"x/gov DepositParams min deposit before upgrade should be 10_000_000 ukava",
)
})
suite.Run("x/gov parameters after upgrade", func() { previousEvmutilBalRes, err := grpcClient.Query.Bank.Balance(beforeUpgradeCtx, &banktypes.QueryBalanceRequest{
suite.Assert().Equal( Address: evmutilAddr,
mustParseDuration("172800s"), Denom: precisebanktypes.IntegerCoinDenom,
govParamsAfter.DepositParams.MaxDepositPeriod, })
"x/gov DepositParams max deposit period after upgrade should be 172800s", suite.Require().NoError(err)
) suite.Require().NotNil(previousEvmutilBalRes.Balance)
suite.Assert().Equal( suite.Require().True(
[]sdk.Coin{{Denom: "ua0gi", Amount: sdk.NewInt(10_000_000)}}, previousEvmutilBalRes.Balance.Amount.IsPositive(),
govParamsAfter.DepositParams.MinDeposit, "should have reserve balance before upgrade",
"x/gov DepositParams min deposit after upgrade should be 10_000_000 ukava",
) )
expectedParams := govtypes.Params{ previousPrecisebankBalRes, err := grpcClient.Query.Bank.Balance(beforeUpgradeCtx, &banktypes.QueryBalanceRequest{
MinDeposit: sdk.NewCoins(sdk.NewCoin("ua0gi", sdk.NewInt(10_000_000))), Address: precisebankAddr,
MaxDepositPeriod: mustParseDuration("172800s"), Denom: precisebanktypes.IntegerCoinDenom,
VotingPeriod: mustParseDuration("30s"),
Quorum: "0.334000000000000000",
Threshold: "0.500000000000000000",
VetoThreshold: "0.334000000000000000",
MinInitialDepositRatio: "0.000000000000000000",
BurnVoteQuorum: false,
BurnProposalDepositPrevote: false,
BurnVoteVeto: true,
}
suite.Require().Equal(expectedParams, *govParamsAfter.Params, "x/gov params after upgrade should be as expected")
}) })
} suite.Require().NoError(err)
suite.Require().NotNil(previousPrecisebankBalRes.Balance)
func (suite *IntegrationTestSuite) TestUpgradeParams_Consensus() { suite.Require().True(
suite.SkipIfUpgradeDisabled() previousPrecisebankBalRes.Balance.Amount.IsZero(),
"should be empty before upgrade",
afterUpgradeCtx := suite.ZgChain.Grpc.CtxAtHeight(suite.UpgradeHeight) )
grpcClient := suite.ZgChain.Grpc suite.T().Logf("x/evmutil balances before upgrade: %s", previousEvmutilBalRes.Balance)
paramsAfter, err := grpcClient.Query.Consensus.Params(afterUpgradeCtx, &consensustypes.QueryParamsRequest{}) suite.T().Logf("x/precisebank balances before upgrade: %s", previousPrecisebankBalRes.Balance)
suite.NoError(err)
// -----------------------------
// v25 consensus params from x/params should be migrated to x/consensus // After upgrade
expectedParams := tmproto.ConsensusParams{ // - Check reserve balance transfer
Block: &tmproto.BlockParams{ // - Check reserve fully backs fractional amounts
MaxBytes: 22020096, afterEvmutilBalRes, err := grpcClient.Query.Bank.Balance(afterUpgradeCtx, &banktypes.QueryBalanceRequest{
MaxGas: 20000000, Address: evmutilAddr,
}, Denom: precisebanktypes.IntegerCoinDenom,
Evidence: &tmproto.EvidenceParams{ })
MaxAgeNumBlocks: 100000, suite.Require().NoError(err)
MaxAgeDuration: *mustParseDuration("172800s"), suite.Require().NotNil(afterEvmutilBalRes.Balance)
MaxBytes: 1048576, suite.Require().Truef(
}, afterEvmutilBalRes.Balance.Amount.IsZero(),
Validator: &tmproto.ValidatorParams{ "should have transferred all reserve balance to precisebank, expected 0 but got %s",
PubKeyTypes: []string{ afterEvmutilBalRes.Balance,
tmtypes.ABCIPubKeyTypeEd25519, )
},
}, afterPrecisebankBalRes, err := grpcClient.Query.Bank.Balance(afterUpgradeCtx, &banktypes.QueryBalanceRequest{
Version: nil, Address: precisebankAddr,
} Denom: precisebanktypes.IntegerCoinDenom,
suite.Require().Equal(expectedParams, *paramsAfter.Params, "x/consensus params after upgrade should be as expected") })
} suite.Require().NoError(err)
suite.Require().NotNil(afterPrecisebankBalRes.Balance)
// func (suite *IntegrationTestSuite) TestUpgradeParams_CDP_Interval() { // 2 total in reserve- genesis.json has 5 accounts with fractional balances
// suite.SkipIfUpgradeDisabled() // totalling 2 integer coins
suite.Require().Equal(int64(2), afterPrecisebankBalRes.Balance.Amount.Int64())
// beforeUpgradeCtx := suite.Kava.Grpc.CtxAtHeight(suite.UpgradeHeight - 1)
// afterUpgradeCtx := suite.Kava.Grpc.CtxAtHeight(suite.UpgradeHeight) suite.T().Logf("x/evmutil balances after upgrade: %s", afterEvmutilBalRes.Balance)
suite.T().Logf("x/precisebank balances after upgrade: %s", afterPrecisebankBalRes.Balance)
// grpcClient := suite.Kava.Grpc
sumFractional, err := grpcClient.Query.Precisebank.TotalFractionalBalances(
// paramsBefore, err := grpcClient.Query.Cdp.Params(beforeUpgradeCtx, &cdptypes.QueryParamsRequest{}) afterUpgradeCtx,
// suite.Require().NoError(err) &precisebanktypes.QueryTotalFractionalBalancesRequest{},
// paramsAfter, err := grpcClient.Query.Cdp.Params(afterUpgradeCtx, &cdptypes.QueryParamsRequest{}) )
// suite.Require().NoError(err) suite.Require().NoError(err)
// expectedParams := paramsBefore.Params suite.Require().Equal(
// expectedParams.LiquidationBlockInterval = int64(50) sumFractional.Total.Amount,
afterPrecisebankBalRes.Balance.Amount.Mul(precisebanktypes.ConversionFactor()),
// suite.Require().Equal(expectedParams, paramsAfter.Params, "reserve should match exactly sum fractional balances",
// "expected cdp parameters to equal previous parameters with a liquidation block interval of 100") )
// }
// Check remainder + total fractional balances = reserve balance
func mustParseDuration(s string) *time.Duration { remainderRes, err := grpcClient.Query.Precisebank.Remainder(
d, err := time.ParseDuration(s) afterUpgradeCtx,
if err != nil { &precisebanktypes.QueryRemainderRequest{},
panic(err) )
} suite.Require().NoError(err)
return &d
sumFractionalAndRemainder := sumFractional.Total.Add(remainderRes.Remainder)
reserveBalanceExtended := afterPrecisebankBalRes.Balance.Amount.Mul(precisebanktypes.ConversionFactor())
suite.Require().Equal(
sumFractionalAndRemainder.Amount,
reserveBalanceExtended,
"remainder + sum(fractional balances) should be = reserve balance",
)
} }

@ -1 +1 @@
Subproject commit 79bb25f47d20c10e70f0539c519240fba82b3302 Subproject commit f78c74549f62d975d8de99c7bd158b3d92e5b145

View File

@ -13,11 +13,9 @@ import (
sdkmath "cosmossdk.io/math" sdkmath "cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/go-bip39"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -208,17 +206,15 @@ func (a *SigningAccount) SignAndBroadcastEvmTx(req util.EvmTxRequest) EvmTxRespo
// SignRawEvmData signs raw evm data with the SigningAccount's private key. // SignRawEvmData signs raw evm data with the SigningAccount's private key.
// It does not broadcast the signed data. // It does not broadcast the signed data.
func (a *SigningAccount) SignRawEvmData(msg []byte) ([]byte, types.PubKey, error) { func (a *SigningAccount) SignRawEvmData(msg []byte) ([]byte, cryptotypes.PubKey, error) {
keyringSigner := emtests.NewSigner(a.evmPrivKey) keyringSigner := emtests.NewSigner(a.evmPrivKey)
return keyringSigner.SignByAddress(a.SdkAddress, msg) return keyringSigner.SignByAddress(a.SdkAddress, msg)
} }
// NewFundedAccount creates a SigningAccount for a random account & funds the account from the whale. // NewFundedAccount creates a SigningAccount for a random account & funds the account from the whale.
func (chain *Chain) NewFundedAccount(name string, funds sdk.Coins) *SigningAccount { func (chain *Chain) NewFundedAccount(name string, funds sdk.Coins) *SigningAccount {
entropy, err := bip39.NewEntropy(128) mnemonic, err := util.RandomMnemonic()
require.NoErrorf(chain.t, err, "failed to generate entropy for account %s: %s", name, err) require.NoError(chain.t, err)
mnemonic, err := bip39.NewMnemonic(entropy)
require.NoErrorf(chain.t, err, "failed to create new mnemonic for account %s: %s", name, err)
acc := chain.AddNewSigningAccount( acc := chain.AddNewSigningAccount(
name, name,

View File

@ -217,7 +217,7 @@ func (suite *E2eTestSuite) SkipIfIbcDisabled() {
} }
// SkipIfUpgradeDisabled should be called at the start of tests that require automated upgrades. // SkipIfUpgradeDisabled should be called at the start of tests that require automated upgrades.
// It gracefully skips the current test if upgrades are dissabled. // It gracefully skips the current test if upgrades are disabled.
// Note: automated upgrade tests are currently only enabled for Kvtool suite runs. // Note: automated upgrade tests are currently only enabled for Kvtool suite runs.
func (suite *E2eTestSuite) SkipIfUpgradeDisabled() { func (suite *E2eTestSuite) SkipIfUpgradeDisabled() {
if suite.config.Kvtool != nil && !suite.config.Kvtool.IncludeAutomatedUpgrade { if suite.config.Kvtool != nil && !suite.config.Kvtool.IncludeAutomatedUpgrade {

View File

@ -1,7 +1,9 @@
package util package util
import ( import (
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/go-bip39"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
@ -12,3 +14,12 @@ func SdkToEvmAddress(addr sdk.AccAddress) common.Address {
func EvmToSdkAddress(addr common.Address) sdk.AccAddress { func EvmToSdkAddress(addr common.Address) sdk.AccAddress {
return sdk.AccAddress(addr.Bytes()) return sdk.AccAddress(addr.Bytes())
} }
// RandomMnemonic generates a random BIP39 mnemonic from 128 bits of entropy
func RandomMnemonic() (string, error) {
entropy, err := bip39.NewEntropy(128)
if err != nil {
return "", errorsmod.Wrap(err, "failed to generate entropy for new mnemonic")
}
return bip39.NewMnemonic(entropy)
}

View File

@ -3,17 +3,21 @@ package util
import ( import (
"context" "context"
"crypto/ecdsa" "crypto/ecdsa"
"encoding/hex"
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
"time" "time"
errorsmod "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/evmos/ethermint/crypto/ethsecp256k1"
) )
var ( var (
@ -77,6 +81,21 @@ func NewEvmSigner(
}, nil }, nil
} }
func NewEvmSignerFromMnemonic(evmClient *ethclient.Client, evmChainId *big.Int, mnemonic string) (*EvmSigner, error) {
hdPath := hd.CreateHDPath(60, 0, 0)
privKeyBytes, err := hd.Secp256k1.Derive()(mnemonic, "", hdPath.String())
if err != nil {
return nil, errorsmod.Wrap(err, "failed to derive private key from mnemonic")
}
privKey := &ethsecp256k1.PrivKey{Key: privKeyBytes}
ecdsaPrivKey, err := crypto.HexToECDSA(hex.EncodeToString(privKey.Bytes()))
if err != nil {
return nil, err
}
return NewEvmSigner(evmClient, ecdsaPrivKey, evmChainId)
}
func (s *EvmSigner) Run(requests <-chan EvmTxRequest) <-chan EvmTxResponse { func (s *EvmSigner) Run(requests <-chan EvmTxRequest) <-chan EvmTxResponse {
responses := make(chan EvmTxResponse) responses := make(chan EvmTxResponse)

View File

@ -358,7 +358,7 @@ func (s *ZgChainSigner) Run(requests <-chan ZgChainMsgRequest) (<-chan ZgChainMs
currentRequest = nil currentRequest = nil
} }
// immediatley response to channel // immediately response to channel
responses <- *response responses <- *response
// go to next request // go to next request
broadcastTxSeq++ broadcastTxSeq++

View File

@ -5,6 +5,12 @@ import "google/protobuf/descriptor.proto";
option go_package = "github.com/cosmos/cosmos-proto;cosmos_proto"; option go_package = "github.com/cosmos/cosmos-proto;cosmos_proto";
extend google.protobuf.MethodOptions {
// method_added_in is used to indicate from which version the method was added.
string method_added_in = 93001;
}
extend google.protobuf.MessageOptions { extend google.protobuf.MessageOptions {
// implements_interface is used to indicate the type name of the interface // implements_interface is used to indicate the type name of the interface
@ -13,6 +19,9 @@ extend google.protobuf.MessageOptions {
// interfaces. Interfaces should be declared using a declare_interface // interfaces. Interfaces should be declared using a declare_interface
// file option. // file option.
repeated string implements_interface = 93001; repeated string implements_interface = 93001;
// message_added_in is used to indicate from which version the message was added.
string message_added_in = 93002;
} }
extend google.protobuf.FieldOptions { extend google.protobuf.FieldOptions {
@ -27,6 +36,9 @@ extend google.protobuf.FieldOptions {
// generators may choose to use this information to map this field to a // generators may choose to use this information to map this field to a
// language-specific type representing the scalar. // language-specific type representing the scalar.
string scalar = 93002; string scalar = 93002;
// field_added_in is used to indicate from which version the field was added.
string field_added_in = 93003;
} }
extend google.protobuf.FileOptions { extend google.protobuf.FileOptions {
@ -46,6 +58,9 @@ extend google.protobuf.FileOptions {
// expected that the declaration will be found in a protobuf file named // expected that the declaration will be found in a protobuf file named
// a/b/scalars.proto in the file descriptor set. // a/b/scalars.proto in the file descriptor set.
repeated ScalarDescriptor declare_scalar = 793022; repeated ScalarDescriptor declare_scalar = 793022;
// file_added_in is used to indicate from which the version the file was added.
string file_added_in = 793023;
} }
// InterfaceDescriptor describes an interface type to be used with // InterfaceDescriptor describes an interface type to be used with

View File

@ -18,12 +18,17 @@ message Params {
repeated int64 extra_eips = 4 [(gogoproto.customname) = "ExtraEIPs", (gogoproto.moretags) = "yaml:\"extra_eips\""]; repeated int64 extra_eips = 4 [(gogoproto.customname) = "ExtraEIPs", (gogoproto.moretags) = "yaml:\"extra_eips\""];
// chain_config defines the EVM chain configuration parameters // chain_config defines the EVM chain configuration parameters
ChainConfig chain_config = 5 [(gogoproto.moretags) = "yaml:\"chain_config\"", (gogoproto.nullable) = false]; ChainConfig chain_config = 5 [(gogoproto.moretags) = "yaml:\"chain_config\"", (gogoproto.nullable) = false];
// list of allowed eip712 msgs and their types // eip712_allowed_msgs contains list of allowed eip712 msgs and their types
repeated EIP712AllowedMsg eip712_allowed_msgs = 6 repeated EIP712AllowedMsg eip712_allowed_msgs = 6
[(gogoproto.customname) = "EIP712AllowedMsgs", (gogoproto.nullable) = false]; [(gogoproto.customname) = "EIP712AllowedMsgs", (gogoproto.nullable) = false];
// allow_unprotected_txs defines if replay-protected (i.e non EIP155 // allow_unprotected_txs defines if replay-protected (i.e non EIP155
// signed) transactions can be executed on the state machine. // signed) transactions can be executed on the state machine.
bool allow_unprotected_txs = 7; bool allow_unprotected_txs = 7;
// enabled_precompiles contains list of hex-encoded evm addresses of enabled precompiled contracts.
// Precompile must be registered before it can be enabled.
// enabled_precompiles should be sorted in ascending order and unique.
// sorting and uniqueness are checked against bytes representation of addresses
repeated string enabled_precompiles = 8;
} }
// ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int values // ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int values
@ -246,20 +251,20 @@ message TraceConfig {
// EIP712AllowedMsg stores an allowed legacy msg and its eip712 type. // EIP712AllowedMsg stores an allowed legacy msg and its eip712 type.
message EIP712AllowedMsg { message EIP712AllowedMsg {
// msg's proto type name. ie "/cosmos.bank.v1beta1.MsgSend" // msg_type_url is a msg's proto type name. ie "/cosmos.bank.v1beta1.MsgSend"
string msg_type_url = 1; string msg_type_url = 1;
// name of the eip712 value type. ie "MsgValueSend" // msg_value_type_name is a name of the eip712 value type. ie "MsgValueSend"
string msg_value_type_name = 2; string msg_value_type_name = 2;
// types of the msg value // value_types is a list of msg value types
repeated EIP712MsgAttrType value_types = 3 [(gogoproto.nullable) = false]; repeated EIP712MsgAttrType value_types = 3 [(gogoproto.nullable) = false];
// nested types of the msg value // nested_types is a list of msg value nested types
repeated EIP712NestedMsgType nested_types = 4 [(gogoproto.nullable) = false]; repeated EIP712NestedMsgType nested_types = 4 [(gogoproto.nullable) = false];
} }
// EIP712MsgType is the eip712 type of a single message. // EIP712NestedMsgType is the eip712 type of a single message.
message EIP712NestedMsgType { message EIP712NestedMsgType {
// name of the nested type. ie "Fee", "Coin" // name of the nested type. ie "Fee", "Coin"
string name = 1; string name = 1;
@ -270,6 +275,8 @@ message EIP712NestedMsgType {
// EIP712MsgAttrType is the eip712 type of a single message attribute. // EIP712MsgAttrType is the eip712 type of a single message attribute.
message EIP712MsgAttrType { message EIP712MsgAttrType {
// name
string name = 1; string name = 1;
// type
string type = 2; string type = 2;
} }

View File

@ -132,7 +132,7 @@ func (suite *ABCITestSuite) TestBeginBlocker_UpdateExpiredAtomicSwaps() {
// Run the second begin blocker // Run the second begin blocker
bep3.BeginBlocker(tc.secondCtx, suite.keeper) bep3.BeginBlocker(tc.secondCtx, suite.keeper)
// Check each swap's availibility and status // Check each swap's availability and status
for _, swapID := range suite.swapIDs { for _, swapID := range suite.swapIDs {
storedSwap, found := suite.keeper.GetAtomicSwap(tc.secondCtx, swapID) storedSwap, found := suite.keeper.GetAtomicSwap(tc.secondCtx, swapID)
if tc.expectInStorage { if tc.expectInStorage {

View File

@ -431,7 +431,7 @@ func (suite *AssetTestSuite) TestIncrementOutgoingAssetSupply() {
true, true,
}, },
{ {
"outoing + amount > current", "outgoing + amount > current",
args{ args{
coin: c("bnb", 36), coin: c("bnb", 36),
}, },

View File

@ -67,7 +67,7 @@ func (a AtomicSwap) Validate() error {
if a.Recipient.Empty() { if a.Recipient.Empty() {
return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "recipient cannot be empty") return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "recipient cannot be empty")
} }
// NOTE: These adresses may not have a bech32 prefix. // NOTE: These addresses may not have a bech32 prefix.
if strings.TrimSpace(a.SenderOtherChain) == "" { if strings.TrimSpace(a.SenderOtherChain) == "" {
return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender other chain cannot be blank") return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender other chain cannot be blank")
} }

View File

@ -185,7 +185,7 @@ func (k Keeper) GetTokenCommitteeProposalResult(ctx sdk.Context, proposalID uint
return false return false
} }
// TallyMemberCommitteeVotes returns the polling status of a token committee vote. Returns yes votes, // TallyTokenCommitteeVotes returns the polling status of a token committee vote. Returns yes votes,
// total current votes, total possible votes (equal to token supply), vote threshold (yes vote ratio // total current votes, total possible votes (equal to token supply), vote threshold (yes vote ratio
// required for proposal to pass), and quorum (votes tallied at this percentage). // required for proposal to pass), and quorum (votes tallied at this percentage).
func (k Keeper) TallyTokenCommitteeVotes(ctx sdk.Context, proposalID uint64, func (k Keeper) TallyTokenCommitteeVotes(ctx sdk.Context, proposalID uint64,

View File

@ -381,7 +381,7 @@ func MustNewProposal(pubProposal PubProposal, id uint64, committeeID uint64, dea
return proposal return proposal
} }
// GetPubProposal returns the PubProposal (govtypes.Content) // GetContent returns the PubProposal (govtypes.Content)
func (p Proposal) GetContent() PubProposal { func (p Proposal) GetContent() PubProposal {
content, ok := p.Content.GetCachedValue().(PubProposal) content, ok := p.Content.GetCachedValue().(PubProposal)
if !ok { if !ok {

View File

@ -7,7 +7,7 @@ import (
proto "github.com/cosmos/gogoproto/proto" proto "github.com/cosmos/gogoproto/proto"
) )
// DefaultNextProposalID is the starting poiint for proposal IDs. // DefaultNextProposalID is the starting point for proposal IDs.
const DefaultNextProposalID uint64 = 1 const DefaultNextProposalID uint64 = 1
// NewGenesisState returns a new genesis state object for the module. // NewGenesisState returns a new genesis state object for the module.

View File

@ -1,282 +0,0 @@
package keeper
import (
"fmt"
errorsmod "cosmossdk.io/errors"
sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
evmtypes "github.com/evmos/ethermint/x/evm/types"
"github.com/0glabs/0g-chain/chaincfg"
"github.com/0glabs/0g-chain/x/evmutil/types"
)
// ConversionMultiplier is the conversion multiplier between evm denom and gas denom
var ConversionMultiplier = sdkmath.NewInt(chaincfg.GasDenomConversionMultiplier)
var _ evmtypes.BankKeeper = EvmBankKeeper{}
// EvmBankKeeper is a BankKeeper wrapper for the x/evm module to allow the use
// of the 18 decimal evm denom coin on the evm.
// x/evm consumes gas and send coins by minting and burning evm denom coins in its module
// account and then sending the funds to the target account.
// This keeper uses both the gas denom coin and a separate evm denom balance to manage the
// extra percision needed by the evm.
type EvmBankKeeper struct {
evmDenomKeeper Keeper
bk types.BankKeeper
ak types.AccountKeeper
}
func NewEvmBankKeeper(baseKeeper Keeper, bk types.BankKeeper, ak types.AccountKeeper) EvmBankKeeper {
return EvmBankKeeper{
evmDenomKeeper: baseKeeper,
bk: bk,
ak: ak,
}
}
// GetBalance returns the total **spendable** balance of evm denom for a given account by address.
func (k EvmBankKeeper) GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin {
if denom != chaincfg.EvmDenom {
panic(fmt.Errorf("only evm denom %s is supported by EvmBankKeeper", chaincfg.EvmDenom))
}
spendableCoins := k.bk.SpendableCoins(ctx, addr)
gasDenomFromBank := spendableCoins.AmountOf(chaincfg.GasDenom)
evmDenomFromBank := spendableCoins.AmountOf(chaincfg.EvmDenom)
evmDenomFromEvmBank := k.evmDenomKeeper.GetBalance(ctx, addr)
var total sdkmath.Int
if gasDenomFromBank.IsPositive() {
total = gasDenomFromBank.Mul(ConversionMultiplier).Add(evmDenomFromBank).Add(evmDenomFromEvmBank)
} else {
total = evmDenomFromBank.Add(evmDenomFromEvmBank)
}
return sdk.NewCoin(chaincfg.EvmDenom, total)
}
// SendCoins transfers evm denom coins from a AccAddress to an AccAddress.
func (k EvmBankKeeper) SendCoins(ctx sdk.Context, senderAddr sdk.AccAddress, recipientAddr sdk.AccAddress, amt sdk.Coins) error {
// SendCoins method is not used by the evm module, but is required by the
// evmtypes.BankKeeper interface. This must be updated if the evm module
// is updated to use SendCoins.
panic("not implemented")
}
// SendCoinsFromModuleToAccount transfers evm denom coins from a ModuleAccount to an AccAddress.
// It will panic if the module account does not exist. An error is returned if the recipient
// address is black-listed or if sending the tokens fails.
func (k EvmBankKeeper) SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error {
gasDenomCoin, baseDemonCnt, err := SplitEvmDenomCoins(amt)
if err != nil {
return err
}
if gasDenomCoin.Amount.IsPositive() {
if err := k.bk.SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, sdk.NewCoins(gasDenomCoin)); err != nil {
return err
}
}
senderAddr := k.GetModuleAddress(senderModule)
if err := k.ConvertOneGasDenomToEvmDenomIfNeeded(ctx, senderAddr, baseDemonCnt); err != nil {
return err
}
if err := k.evmDenomKeeper.SendBalance(ctx, senderAddr, recipientAddr, baseDemonCnt); err != nil {
return err
}
return k.ConvertEvmDenomToGasDenom(ctx, recipientAddr)
}
// SendCoinsFromAccountToModule transfers evm denom coins from an AccAddress to a ModuleAccount.
// It will panic if the module account does not exist.
func (k EvmBankKeeper) SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error {
gasDenomCoin, evmDenomCnt, err := SplitEvmDenomCoins(amt)
if err != nil {
return err
}
if gasDenomCoin.IsPositive() {
if err := k.bk.SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, sdk.NewCoins(gasDenomCoin)); err != nil {
return err
}
}
if err := k.ConvertOneGasDenomToEvmDenomIfNeeded(ctx, senderAddr, evmDenomCnt); err != nil {
return err
}
recipientAddr := k.GetModuleAddress(recipientModule)
if err := k.evmDenomKeeper.SendBalance(ctx, senderAddr, recipientAddr, evmDenomCnt); err != nil {
return err
}
return k.ConvertEvmDenomToGasDenom(ctx, recipientAddr)
}
// MintCoins mints evm denom coins by minting the equivalent gas denom coins and any remaining evm denom coins.
// It will panic if the module account does not exist or is unauthorized.
func (k EvmBankKeeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error {
gasDenomCoin, baseDemonCnt, err := SplitEvmDenomCoins(amt)
if err != nil {
return err
}
if gasDenomCoin.IsPositive() {
if err := k.bk.MintCoins(ctx, moduleName, sdk.NewCoins(gasDenomCoin)); err != nil {
return err
}
}
recipientAddr := k.GetModuleAddress(moduleName)
if err := k.evmDenomKeeper.AddBalance(ctx, recipientAddr, baseDemonCnt); err != nil {
return err
}
return k.ConvertEvmDenomToGasDenom(ctx, recipientAddr)
}
// BurnCoins burns evm denom coins by burning the equivalent gas denom coins and any remaining evm denom coins.
// It will panic if the module account does not exist or is unauthorized.
func (k EvmBankKeeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error {
gasDenomCoin, baseDemonCnt, err := SplitEvmDenomCoins(amt)
if err != nil {
return err
}
if gasDenomCoin.IsPositive() {
if err := k.bk.BurnCoins(ctx, moduleName, sdk.NewCoins(gasDenomCoin)); err != nil {
return err
}
}
moduleAddr := k.GetModuleAddress(moduleName)
if err := k.ConvertOneGasDenomToEvmDenomIfNeeded(ctx, moduleAddr, baseDemonCnt); err != nil {
return err
}
return k.evmDenomKeeper.RemoveBalance(ctx, moduleAddr, baseDemonCnt)
}
// IsSendEnabledCoins checks the coins provided and returns an ErrSendDisabled
// if any of the coins are not configured for sending. Returns nil if sending is
// enabled for all provided coins.
func (k EvmBankKeeper) IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error {
// IsSendEnabledCoins method is not used by the evm module, but is required by the
// evmtypes.BankKeeper interface. This must be updated if the evm module
// is updated to use IsSendEnabledCoins.
panic("not implemented")
}
// ConvertOnegasDenomToEvmDenomIfNeeded converts 1 gas denom to evm denom for an address if
// its evm denom balance is smaller than the evmDenomCnt amount.
func (k EvmBankKeeper) ConvertOneGasDenomToEvmDenomIfNeeded(ctx sdk.Context, addr sdk.AccAddress, evmDenomCnt sdkmath.Int) error {
evmDenomBal := k.evmDenomKeeper.GetBalance(ctx, addr)
if evmDenomBal.GTE(evmDenomCnt) {
return nil
}
gasDenomToStore := sdk.NewCoins(sdk.NewCoin(chaincfg.GasDenom, sdk.OneInt()))
if err := k.bk.SendCoinsFromAccountToModule(ctx, addr, types.ModuleName, gasDenomToStore); err != nil {
return err
}
// add 1 gas denom equivalent of evm denom to addr
evmDenomToReceive := ConversionMultiplier
if err := k.evmDenomKeeper.AddBalance(ctx, addr, evmDenomToReceive); err != nil {
return err
}
return nil
}
// ConvertEvmDenomTogasDenom converts all available evm denom to gas denom for a given AccAddress.
func (k EvmBankKeeper) ConvertEvmDenomToGasDenom(ctx sdk.Context, addr sdk.AccAddress) error {
totalEvmDenom := k.evmDenomKeeper.GetBalance(ctx, addr)
gasDenomCoin, _, err := SplitEvmDenomCoins(sdk.NewCoins(sdk.NewCoin(chaincfg.EvmDenom, totalEvmDenom)))
if err != nil {
return err
}
// do nothing if account does not have enough evm denom for a single gas denom
gasDenomToReceive := gasDenomCoin.Amount
if !gasDenomToReceive.IsPositive() {
return nil
}
// remove evm denom used for converting to gas denom
evmDenomToBurn := gasDenomToReceive.Mul(ConversionMultiplier)
finalBal := totalEvmDenom.Sub(evmDenomToBurn)
if err := k.evmDenomKeeper.SetBalance(ctx, addr, finalBal); err != nil {
return err
}
fromAddr := k.GetModuleAddress(types.ModuleName)
if err := k.bk.SendCoins(ctx, fromAddr, addr, sdk.NewCoins(gasDenomCoin)); err != nil {
return err
}
return nil
}
func (k EvmBankKeeper) GetModuleAddress(moduleName string) sdk.AccAddress {
addr := k.ak.GetModuleAddress(moduleName)
if addr == nil {
panic(errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleName))
}
return addr
}
// SplitEvmDenomCoins splits evm denom coins to the equivalent gas denom coins and any remaining evm denom balance.
// An error will be returned if the coins are not valid or if the coins are not the evm denom.
func SplitEvmDenomCoins(coins sdk.Coins) (sdk.Coin, sdkmath.Int, error) {
baseDemonCnt := sdk.ZeroInt()
gasDenomAmt := sdk.NewCoin(chaincfg.GasDenom, sdk.ZeroInt())
if len(coins) == 0 {
return gasDenomAmt, baseDemonCnt, nil
}
if err := ValidateEvmCoins(coins); err != nil {
return gasDenomAmt, baseDemonCnt, err
}
// note: we should always have len(coins) == 1 here since coins cannot have dup denoms after we validate.
coin := coins[0]
remainingBalance := coin.Amount.Mod(ConversionMultiplier)
if remainingBalance.IsPositive() {
baseDemonCnt = remainingBalance
}
gasDenomAmount := coin.Amount.Quo(ConversionMultiplier)
if gasDenomAmount.IsPositive() {
gasDenomAmt = sdk.NewCoin(chaincfg.GasDenom, gasDenomAmount)
}
return gasDenomAmt, baseDemonCnt, nil
}
// ValidateEvmCoins validates the coins from evm is valid and is the evm denom.
func ValidateEvmCoins(coins sdk.Coins) error {
if len(coins) == 0 {
return nil
}
// validate that coins are non-negative, sorted, and no dup denoms
if err := coins.Validate(); err != nil {
return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, coins.String())
}
// validate that coin denom is evm denom
if len(coins) != 1 || coins[0].Denom != chaincfg.EvmDenom {
errMsg := fmt.Sprintf("invalid evm coin denom, only %s is supported", chaincfg.EvmDenom)
return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, errMsg)
}
return nil
}

View File

@ -1,805 +0,0 @@
package keeper_test
import (
"math/big"
"testing"
"time"
sdkmath "cosmossdk.io/math"
tmtime "github.com/cometbft/cometbft/types/time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/suite"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
vesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
evmtypes "github.com/evmos/ethermint/x/evm/types"
"github.com/0glabs/0g-chain/chaincfg"
"github.com/0glabs/0g-chain/x/evmutil/keeper"
"github.com/0glabs/0g-chain/x/evmutil/testutil"
"github.com/0glabs/0g-chain/x/evmutil/types"
)
type evmBankKeeperTestSuite struct {
testutil.Suite
}
func (suite *evmBankKeeperTestSuite) SetupTest() {
suite.Suite.SetupTest()
}
func (suite *evmBankKeeperTestSuite) TestGetBalance_ReturnsSpendable() {
startingCoins := sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10))
startingEvmDenom := sdkmath.NewInt(100)
now := tmtime.Now()
endTime := now.Add(24 * time.Hour)
bacc := authtypes.NewBaseAccountWithAddress(suite.Addrs[0])
vacc := vesting.NewContinuousVestingAccount(bacc, startingCoins, now.Unix(), endTime.Unix())
suite.AccountKeeper.SetAccount(suite.Ctx, vacc)
err := suite.App.FundAccount(suite.Ctx, suite.Addrs[0], startingCoins)
suite.Require().NoError(err)
err = suite.Keeper.SetBalance(suite.Ctx, suite.Addrs[0], startingEvmDenom)
suite.Require().NoError(err)
coin := suite.EvmBankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], chaincfg.EvmDenom)
suite.Require().Equal(startingEvmDenom, coin.Amount)
ctx := suite.Ctx.WithBlockTime(now.Add(12 * time.Hour))
coin = suite.EvmBankKeeper.GetBalance(ctx, suite.Addrs[0], chaincfg.EvmDenom)
suite.Require().Equal(sdkmath.NewIntFromUint64(5_000_000_000_100), coin.Amount)
}
func (suite *evmBankKeeperTestSuite) TestGetBalance_NotEvmDenom() {
suite.Require().Panics(func() {
suite.EvmBankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], chaincfg.GasDenom)
})
suite.Require().Panics(func() {
suite.EvmBankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], "busd")
})
}
func (suite *evmBankKeeperTestSuite) TestGetBalance() {
tests := []struct {
name string
startingAmount sdk.Coins
expAmount sdkmath.Int
}{
{
"gas denom with evm denom",
sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 100),
sdk.NewInt64Coin(chaincfg.GasDenom, 10),
),
sdkmath.NewInt(10_000_000_000_100),
},
{
"just evm denom",
sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 100),
sdk.NewInt64Coin("busd", 100),
),
sdkmath.NewInt(100),
},
{
"just gas denom",
sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.GasDenom, 10),
sdk.NewInt64Coin("busd", 100),
),
sdkmath.NewInt(10_000_000_000_000),
},
{
"no gas denom or evm denom",
sdk.NewCoins(),
sdk.ZeroInt(),
},
{
"with avaka that is more than 1 gas denom",
sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 20_000_000_000_220),
sdk.NewInt64Coin(chaincfg.GasDenom, 11),
),
sdkmath.NewInt(31_000_000_000_220),
},
}
for _, tt := range tests {
suite.Run(tt.name, func() {
suite.SetupTest()
suite.FundAccountWithZgChain(suite.Addrs[0], tt.startingAmount)
coin := suite.EvmBankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], chaincfg.EvmDenom)
suite.Require().Equal(tt.expAmount, coin.Amount)
})
}
}
func (suite *evmBankKeeperTestSuite) TestSendCoinsFromModuleToAccount() {
startingModuleCoins := sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 200),
sdk.NewInt64Coin(chaincfg.GasDenom, 100),
)
tests := []struct {
name string
sendCoins sdk.Coins
startingAccBal sdk.Coins
expAccBal sdk.Coins
hasErr bool
}{
{
"send more than 1 gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 12_000_000_000_010)),
sdk.Coins{},
sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 10),
sdk.NewInt64Coin(chaincfg.GasDenom, 12),
),
false,
},
{
"send less than 1 gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 122)),
sdk.Coins{},
sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 122),
sdk.NewInt64Coin(chaincfg.GasDenom, 0),
),
false,
},
{
"send an exact amount of gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 98_000_000_000_000)),
sdk.Coins{},
sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 0o0),
sdk.NewInt64Coin(chaincfg.GasDenom, 98),
),
false,
},
{
"send no evm denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 0)),
sdk.Coins{},
sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 0),
sdk.NewInt64Coin(chaincfg.GasDenom, 0),
),
false,
},
{
"errors if sending other coins",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 500), sdk.NewInt64Coin("busd", 1000)),
sdk.Coins{},
sdk.Coins{},
true,
},
{
"errors if not enough total evm denom to cover",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_001_000)),
sdk.Coins{},
sdk.Coins{},
true,
},
{
"errors if not enough gas denom to cover",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 200_000_000_000_000)),
sdk.Coins{},
sdk.Coins{},
true,
},
{
"converts receiver's evm denom to gas denom if there's enough evm denom after the transfer",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 99_000_000_000_200)),
sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 999_999_999_900),
sdk.NewInt64Coin(chaincfg.GasDenom, 1),
),
sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 100),
sdk.NewInt64Coin(chaincfg.GasDenom, 101),
),
false,
},
{
"converts all of receiver's evm denom to gas denom even if somehow receiver has more than 1 gas denom of evm denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 12_000_000_000_100)),
sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 5_999_999_999_990),
sdk.NewInt64Coin(chaincfg.GasDenom, 1),
),
sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 90),
sdk.NewInt64Coin(chaincfg.GasDenom, 19),
),
false,
},
{
"swap 1 gas denom for evm denom if module account doesn't have enough evm denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 99_000_000_001_000)),
sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 200),
sdk.NewInt64Coin(chaincfg.GasDenom, 1),
),
sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 1200),
sdk.NewInt64Coin(chaincfg.GasDenom, 100),
),
false,
},
}
for _, tt := range tests {
suite.Run(tt.name, func() {
suite.SetupTest()
suite.FundAccountWithZgChain(suite.Addrs[0], tt.startingAccBal)
suite.FundModuleAccountWithZgChain(evmtypes.ModuleName, startingModuleCoins)
// fund our module with some gas denom to account for converting extra evm denom back to gas denom
suite.FundModuleAccountWithZgChain(types.ModuleName, sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10)))
err := suite.EvmBankKeeper.SendCoinsFromModuleToAccount(suite.Ctx, evmtypes.ModuleName, suite.Addrs[0], tt.sendCoins)
if tt.hasErr {
suite.Require().Error(err)
return
} else {
suite.Require().NoError(err)
}
// check gas denom
GasDenomSender := suite.BankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], chaincfg.GasDenom)
suite.Require().Equal(tt.expAccBal.AmountOf(chaincfg.GasDenom).Int64(), GasDenomSender.Amount.Int64())
// check evm denom
actualEvmDenom := suite.Keeper.GetBalance(suite.Ctx, suite.Addrs[0])
suite.Require().Equal(tt.expAccBal.AmountOf(chaincfg.EvmDenom).Int64(), actualEvmDenom.Int64())
})
}
}
func (suite *evmBankKeeperTestSuite) TestSendCoinsFromAccountToModule() {
startingAccCoins := sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 200),
sdk.NewInt64Coin(chaincfg.GasDenom, 100),
)
startingModuleCoins := sdk.NewCoins(
sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_000),
)
tests := []struct {
name string
sendCoins sdk.Coins
expSenderCoins sdk.Coins
expModuleCoins sdk.Coins
hasErr bool
}{
{
"send more than 1 gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 12_000_000_000_010)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 190), sdk.NewInt64Coin(chaincfg.GasDenom, 88)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_010), sdk.NewInt64Coin(chaincfg.GasDenom, 12)),
false,
},
{
"send less than 1 gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 122)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 78), sdk.NewInt64Coin(chaincfg.GasDenom, 100)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_122), sdk.NewInt64Coin(chaincfg.GasDenom, 0)),
false,
},
{
"send an exact amount of gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 98_000_000_000_000)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 200), sdk.NewInt64Coin(chaincfg.GasDenom, 2)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_000), sdk.NewInt64Coin(chaincfg.GasDenom, 98)),
false,
},
{
"send no evm denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 0)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 200), sdk.NewInt64Coin(chaincfg.GasDenom, 100)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_000), sdk.NewInt64Coin(chaincfg.GasDenom, 0)),
false,
},
{
"errors if sending other coins",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 500), sdk.NewInt64Coin("busd", 1000)),
sdk.Coins{},
sdk.Coins{},
true,
},
{
"errors if have dup coins",
sdk.Coins{
sdk.NewInt64Coin(chaincfg.EvmDenom, 12_000_000_000_000),
sdk.NewInt64Coin(chaincfg.EvmDenom, 2_000_000_000_000),
},
sdk.Coins{},
sdk.Coins{},
true,
},
{
"errors if not enough total evm denom to cover",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_001_000)),
sdk.Coins{},
sdk.Coins{},
true,
},
{
"errors if not enough gas denom to cover",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 200_000_000_000_000)),
sdk.Coins{},
sdk.Coins{},
true,
},
{
"converts 1 gas denom to evm denom if not enough evm denom to cover",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 99_001_000_000_000)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 999_000_000_200), sdk.NewInt64Coin(chaincfg.GasDenom, 0)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 101_000_000_000), sdk.NewInt64Coin(chaincfg.GasDenom, 99)),
false,
},
{
"converts receiver's evm denom to gas denom if there's enough evm denom after the transfer",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 5_900_000_000_200)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_000), sdk.NewInt64Coin(chaincfg.GasDenom, 94)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 200), sdk.NewInt64Coin(chaincfg.GasDenom, 6)),
false,
},
}
for _, tt := range tests {
suite.Run(tt.name, func() {
suite.SetupTest()
suite.FundAccountWithZgChain(suite.Addrs[0], startingAccCoins)
suite.FundModuleAccountWithZgChain(evmtypes.ModuleName, startingModuleCoins)
err := suite.EvmBankKeeper.SendCoinsFromAccountToModule(suite.Ctx, suite.Addrs[0], evmtypes.ModuleName, tt.sendCoins)
if tt.hasErr {
suite.Require().Error(err)
return
} else {
suite.Require().NoError(err)
}
// check sender balance
GasDenomSender := suite.BankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], chaincfg.GasDenom)
suite.Require().Equal(tt.expSenderCoins.AmountOf(chaincfg.GasDenom).Int64(), GasDenomSender.Amount.Int64())
actualEvmDenom := suite.Keeper.GetBalance(suite.Ctx, suite.Addrs[0])
suite.Require().Equal(tt.expSenderCoins.AmountOf(chaincfg.EvmDenom).Int64(), actualEvmDenom.Int64())
// check module balance
moduleAddr := suite.AccountKeeper.GetModuleAddress(evmtypes.ModuleName)
GasDenomSender = suite.BankKeeper.GetBalance(suite.Ctx, moduleAddr, chaincfg.GasDenom)
suite.Require().Equal(tt.expModuleCoins.AmountOf(chaincfg.GasDenom).Int64(), GasDenomSender.Amount.Int64())
actualEvmDenom = suite.Keeper.GetBalance(suite.Ctx, moduleAddr)
suite.Require().Equal(tt.expModuleCoins.AmountOf(chaincfg.EvmDenom).Int64(), actualEvmDenom.Int64())
})
}
}
func (suite *evmBankKeeperTestSuite) TestBurnCoins() {
startingGasDenom := sdkmath.NewInt(100)
tests := []struct {
name string
burnCoins sdk.Coins
expGasDenom sdkmath.Int
expEvmDenom sdkmath.Int
hasErr bool
evmDenomStart sdkmath.Int
}{
{
"burn more than 1 gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 12_021_000_000_002)),
sdkmath.NewInt(88),
sdkmath.NewInt(100_000_000_000),
false,
sdkmath.NewInt(121_000_000_002),
},
{
"burn less than 1 gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 122)),
sdkmath.NewInt(100),
sdkmath.NewInt(878),
false,
sdkmath.NewInt(1000),
},
{
"burn an exact amount of gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 98_000_000_000_000)),
sdkmath.NewInt(2),
sdkmath.NewInt(10),
false,
sdkmath.NewInt(10),
},
{
"burn no evm denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 0)),
startingGasDenom,
sdk.ZeroInt(),
false,
sdk.ZeroInt(),
},
{
"errors if burning other coins",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 500), sdk.NewInt64Coin("busd", 1000)),
startingGasDenom,
sdkmath.NewInt(100),
true,
sdkmath.NewInt(100),
},
{
"errors if have dup coins",
sdk.Coins{
sdk.NewInt64Coin(chaincfg.EvmDenom, 12_000_000_000_000),
sdk.NewInt64Coin(chaincfg.EvmDenom, 2_000_000_000_000),
},
startingGasDenom,
sdk.ZeroInt(),
true,
sdk.ZeroInt(),
},
{
"errors if burn amount is negative",
sdk.Coins{sdk.Coin{Denom: chaincfg.EvmDenom, Amount: sdkmath.NewInt(-100)}},
startingGasDenom,
sdkmath.NewInt(50),
true,
sdkmath.NewInt(50),
},
{
"errors if not enough evm denom to cover burn",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_999_000_000_000)),
sdkmath.NewInt(0),
sdkmath.NewInt(99_000_000_000),
true,
sdkmath.NewInt(99_000_000_000),
},
{
"errors if not enough gas denom to cover burn",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 200_000_000_000_000)),
sdkmath.NewInt(100),
sdk.ZeroInt(),
true,
sdk.ZeroInt(),
},
{
"converts 1 gas denom to evm denom if not enough evm denom to cover",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 12_021_000_000_002)),
sdkmath.NewInt(87),
sdkmath.NewInt(980_000_000_000),
false,
sdkmath.NewInt(1_000_000_002),
},
}
for _, tt := range tests {
suite.Run(tt.name, func() {
suite.SetupTest()
startingCoins := sdk.NewCoins(
sdk.NewCoin(chaincfg.GasDenom, startingGasDenom),
sdk.NewCoin(chaincfg.EvmDenom, tt.evmDenomStart),
)
suite.FundModuleAccountWithZgChain(evmtypes.ModuleName, startingCoins)
err := suite.EvmBankKeeper.BurnCoins(suite.Ctx, evmtypes.ModuleName, tt.burnCoins)
if tt.hasErr {
suite.Require().Error(err)
return
} else {
suite.Require().NoError(err)
}
// check gas denom
GasDenomActual := suite.BankKeeper.GetBalance(suite.Ctx, suite.EvmModuleAddr, chaincfg.GasDenom)
suite.Require().Equal(tt.expGasDenom, GasDenomActual.Amount)
// check evm denom
evmDenomActual := suite.Keeper.GetBalance(suite.Ctx, suite.EvmModuleAddr)
suite.Require().Equal(tt.expEvmDenom, evmDenomActual)
})
}
}
func (suite *evmBankKeeperTestSuite) TestMintCoins() {
tests := []struct {
name string
mintCoins sdk.Coins
GasDenomCnt sdkmath.Int
evmDenomCnt sdkmath.Int
hasErr bool
evmDenomStart sdkmath.Int
}{
{
"mint more than 1 gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 12_021_000_000_002)),
sdkmath.NewInt(12),
sdkmath.NewInt(21_000_000_002),
false,
sdk.ZeroInt(),
},
{
"mint less than 1 gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 901_000_000_001)),
sdk.ZeroInt(),
sdkmath.NewInt(901_000_000_001),
false,
sdk.ZeroInt(),
},
{
"mint an exact amount of gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 123_000_000_000_000_000)),
sdkmath.NewInt(123_000),
sdk.ZeroInt(),
false,
sdk.ZeroInt(),
},
{
"mint no evm denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 0)),
sdk.ZeroInt(),
sdk.ZeroInt(),
false,
sdk.ZeroInt(),
},
{
"errors if minting other coins",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 500), sdk.NewInt64Coin("busd", 1000)),
sdk.ZeroInt(),
sdkmath.NewInt(100),
true,
sdkmath.NewInt(100),
},
{
"errors if have dup coins",
sdk.Coins{
sdk.NewInt64Coin(chaincfg.EvmDenom, 12_000_000_000_000),
sdk.NewInt64Coin(chaincfg.EvmDenom, 2_000_000_000_000),
},
sdk.ZeroInt(),
sdk.ZeroInt(),
true,
sdk.ZeroInt(),
},
{
"errors if mint amount is negative",
sdk.Coins{sdk.Coin{Denom: chaincfg.EvmDenom, Amount: sdkmath.NewInt(-100)}},
sdk.ZeroInt(),
sdkmath.NewInt(50),
true,
sdkmath.NewInt(50),
},
{
"adds to existing evm denom balance",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 12_021_000_000_002)),
sdkmath.NewInt(12),
sdkmath.NewInt(21_000_000_102),
false,
sdkmath.NewInt(100),
},
{
"convert evm denom balance to gas denom if it exceeds 1 gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 10_999_000_000_000)),
sdkmath.NewInt(12),
sdkmath.NewInt(1_200_000_001),
false,
sdkmath.NewInt(1_002_200_000_001),
},
}
for _, tt := range tests {
suite.Run(tt.name, func() {
suite.SetupTest()
suite.FundModuleAccountWithZgChain(types.ModuleName, sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10)))
suite.FundModuleAccountWithZgChain(evmtypes.ModuleName, sdk.NewCoins(sdk.NewCoin(chaincfg.EvmDenom, tt.evmDenomStart)))
err := suite.EvmBankKeeper.MintCoins(suite.Ctx, evmtypes.ModuleName, tt.mintCoins)
if tt.hasErr {
suite.Require().Error(err)
return
} else {
suite.Require().NoError(err)
}
// check gas denom
GasDenomActual := suite.BankKeeper.GetBalance(suite.Ctx, suite.EvmModuleAddr, chaincfg.GasDenom)
suite.Require().Equal(tt.GasDenomCnt, GasDenomActual.Amount)
// check evm denom
evmDenomActual := suite.Keeper.GetBalance(suite.Ctx, suite.EvmModuleAddr)
suite.Require().Equal(tt.evmDenomCnt, evmDenomActual)
})
}
}
func (suite *evmBankKeeperTestSuite) TestValidateEvmCoins() {
tests := []struct {
name string
coins sdk.Coins
shouldErr bool
}{
{
"valid coins",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 500)),
false,
},
{
"dup coins",
sdk.Coins{sdk.NewInt64Coin(chaincfg.EvmDenom, 500), sdk.NewInt64Coin(chaincfg.EvmDenom, 500)},
true,
},
{
"not evm coins",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 500)),
true,
},
{
"negative coins",
sdk.Coins{sdk.Coin{Denom: chaincfg.EvmDenom, Amount: sdkmath.NewInt(-500)}},
true,
},
}
for _, tt := range tests {
suite.Run(tt.name, func() {
err := keeper.ValidateEvmCoins(tt.coins)
if tt.shouldErr {
suite.Require().Error(err)
} else {
suite.Require().NoError(err)
}
})
}
}
func (suite *evmBankKeeperTestSuite) TestConvertOneGasDenomToEvmDenomIfNeeded() {
evmDenomNeeded := sdkmath.NewInt(200)
tests := []struct {
name string
startingCoins sdk.Coins
expectedCoins sdk.Coins
success bool
}{
{
"not enough gas denom for conversion",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100)),
false,
},
{
"converts 1 gas denom to evm denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10), sdk.NewInt64Coin(chaincfg.EvmDenom, 100)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 9), sdk.NewInt64Coin(chaincfg.EvmDenom, 1_000_000_000_100)),
true,
},
{
"conversion not needed",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10), sdk.NewInt64Coin(chaincfg.EvmDenom, 200)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10), sdk.NewInt64Coin(chaincfg.EvmDenom, 200)),
true,
},
}
for _, tt := range tests {
suite.Run(tt.name, func() {
suite.SetupTest()
suite.FundAccountWithZgChain(suite.Addrs[0], tt.startingCoins)
err := suite.EvmBankKeeper.ConvertOneGasDenomToEvmDenomIfNeeded(suite.Ctx, suite.Addrs[0], evmDenomNeeded)
moduleZgChain := suite.BankKeeper.GetBalance(suite.Ctx, suite.AccountKeeper.GetModuleAddress(types.ModuleName), chaincfg.GasDenom)
if tt.success {
suite.Require().NoError(err)
if tt.startingCoins.AmountOf(chaincfg.EvmDenom).LT(evmDenomNeeded) {
suite.Require().Equal(sdk.OneInt(), moduleZgChain.Amount)
}
} else {
suite.Require().Error(err)
suite.Require().Equal(sdk.ZeroInt(), moduleZgChain.Amount)
}
evmDenomCnt := suite.Keeper.GetBalance(suite.Ctx, suite.Addrs[0])
suite.Require().Equal(tt.expectedCoins.AmountOf(chaincfg.EvmDenom), evmDenomCnt)
GasDenomCoin := suite.BankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], chaincfg.GasDenom)
suite.Require().Equal(tt.expectedCoins.AmountOf(chaincfg.GasDenom), GasDenomCoin.Amount)
})
}
}
func (suite *evmBankKeeperTestSuite) TestConvertEvmDenomToGasDenom() {
tests := []struct {
name string
startingCoins sdk.Coins
expectedCoins sdk.Coins
}{
{
"not enough gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100), sdk.NewInt64Coin(chaincfg.GasDenom, 0)),
},
{
"converts evm denom for 1 gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10), sdk.NewInt64Coin(chaincfg.EvmDenom, 1_000_000_000_003)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 11), sdk.NewInt64Coin(chaincfg.EvmDenom, 3)),
},
{
"converts more than 1 gas denom of evm denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10), sdk.NewInt64Coin(chaincfg.EvmDenom, 8_000_000_000_123)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 18), sdk.NewInt64Coin(chaincfg.EvmDenom, 123)),
},
}
for _, tt := range tests {
suite.Run(tt.name, func() {
suite.SetupTest()
err := suite.App.FundModuleAccount(suite.Ctx, types.ModuleName, sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10)))
suite.Require().NoError(err)
suite.FundAccountWithZgChain(suite.Addrs[0], tt.startingCoins)
err = suite.EvmBankKeeper.ConvertEvmDenomToGasDenom(suite.Ctx, suite.Addrs[0])
suite.Require().NoError(err)
evmDenomCnt := suite.Keeper.GetBalance(suite.Ctx, suite.Addrs[0])
suite.Require().Equal(tt.expectedCoins.AmountOf(chaincfg.EvmDenom), evmDenomCnt)
GasDenomCoin := suite.BankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], chaincfg.GasDenom)
suite.Require().Equal(tt.expectedCoins.AmountOf(chaincfg.GasDenom), GasDenomCoin.Amount)
})
}
}
func (suite *evmBankKeeperTestSuite) TestSplitEvmDenomCoins() {
tests := []struct {
name string
coins sdk.Coins
expectedCoins sdk.Coins
shouldErr bool
}{
{
"invalid coins",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 500)),
nil,
true,
},
{
"empty coins",
sdk.NewCoins(),
sdk.NewCoins(),
false,
},
{
"gas denom & evm denom coins",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 8_000_000_000_123)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 8), sdk.NewInt64Coin(chaincfg.EvmDenom, 123)),
false,
},
{
"only evm denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 10_123)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 10_123)),
false,
},
{
"only gas denom",
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 5_000_000_000_000)),
sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 5)),
false,
},
}
for _, tt := range tests {
suite.Run(tt.name, func() {
GasDenomCoin, evmDenomCnt, err := keeper.SplitEvmDenomCoins(tt.coins)
if tt.shouldErr {
suite.Require().Error(err)
} else {
suite.Require().NoError(err)
suite.Require().Equal(tt.expectedCoins.AmountOf(chaincfg.GasDenom), GasDenomCoin.Amount)
suite.Require().Equal(tt.expectedCoins.AmountOf(chaincfg.EvmDenom), evmDenomCnt)
}
})
}
}
func TestEvmBankKeeperTestSuite(t *testing.T) {
suite.Run(t, new(evmBankKeeperTestSuite))
}
func makeBigIntByString(s string) *big.Int {
i, _ := new(big.Int).SetString(s, 10)
return i
}

View File

@ -6,14 +6,11 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/0glabs/0g-chain/chaincfg"
"github.com/0glabs/0g-chain/x/evmutil/types" "github.com/0glabs/0g-chain/x/evmutil/types"
) )
// RegisterInvariants registers the swap module invariants // RegisterInvariants registers the swap module invariants
func RegisterInvariants(ir sdk.InvariantRegistry, bankK types.BankKeeper, k Keeper) { func RegisterInvariants(ir sdk.InvariantRegistry, bankK types.BankKeeper, k Keeper) {
ir.RegisterRoute(types.ModuleName, "fully-backed", FullyBackedInvariant(bankK, k))
ir.RegisterRoute(types.ModuleName, "small-balances", SmallBalancesInvariant(bankK, k))
ir.RegisterRoute(types.ModuleName, "cosmos-coins-fully-backed", CosmosCoinsFullyBackedInvariant(bankK, k)) ir.RegisterRoute(types.ModuleName, "cosmos-coins-fully-backed", CosmosCoinsFullyBackedInvariant(bankK, k))
// Disable this invariant due to some issues with it requiring some staking params to be set in genesis. // Disable this invariant due to some issues with it requiring some staking params to be set in genesis.
// ir.RegisterRoute(types.ModuleName, "backed-conversion-coins", BackedCoinsInvariant(bankK, k)) // ir.RegisterRoute(types.ModuleName, "backed-conversion-coins", BackedCoinsInvariant(bankK, k))
@ -22,57 +19,11 @@ func RegisterInvariants(ir sdk.InvariantRegistry, bankK types.BankKeeper, k Keep
// AllInvariants runs all invariants of the swap module // AllInvariants runs all invariants of the swap module
func AllInvariants(bankK types.BankKeeper, k Keeper) sdk.Invariant { func AllInvariants(bankK types.BankKeeper, k Keeper) sdk.Invariant {
return func(ctx sdk.Context) (string, bool) { return func(ctx sdk.Context) (string, bool) {
if res, stop := FullyBackedInvariant(bankK, k)(ctx); stop {
return res, stop
}
if res, stop := BackedCoinsInvariant(bankK, k)(ctx); stop { if res, stop := BackedCoinsInvariant(bankK, k)(ctx); stop {
return res, stop return res, stop
} }
if res, stop := CosmosCoinsFullyBackedInvariant(bankK, k)(ctx); stop {
return res, stop
}
return SmallBalancesInvariant(bankK, k)(ctx)
}
}
// FullyBackedInvariant ensures all minor balances are backed by the coins in the module account. return CosmosCoinsFullyBackedInvariant(bankK, k)(ctx)
//
// The module balance can be greater than the sum of all minor balances. This can happen in rare cases
// where the evm module burns tokens.
func FullyBackedInvariant(bankK types.BankKeeper, k Keeper) sdk.Invariant {
broken := false
message := sdk.FormatInvariant(types.ModuleName, "fully backed broken", "sum of minor balances greater than module account")
return func(ctx sdk.Context) (string, bool) {
totalMinorBalances := sdk.ZeroInt()
k.IterateAllAccounts(ctx, func(acc types.Account) bool {
totalMinorBalances = totalMinorBalances.Add(acc.Balance)
return false
})
bankAddr := authtypes.NewModuleAddress(types.ModuleName)
bankBalance := bankK.GetBalance(ctx, bankAddr, chaincfg.GasDenom).Amount.Mul(ConversionMultiplier)
broken = totalMinorBalances.GT(bankBalance)
return message, broken
}
}
// SmallBalancesInvariant ensures all minor balances are less than the overflow amount, beyond this they should be converted to the major denom.
func SmallBalancesInvariant(_ types.BankKeeper, k Keeper) sdk.Invariant {
broken := false
message := sdk.FormatInvariant(types.ModuleName, "small balances broken", "minor balances not all less than overflow")
return func(ctx sdk.Context) (string, bool) {
k.IterateAllAccounts(ctx, func(account types.Account) bool {
if account.Balance.GTE(ConversionMultiplier) {
broken = true
return true
}
return false
})
return message, broken
} }
} }

View File

@ -44,7 +44,7 @@ func (suite *invariantTestSuite) SetupValidState() {
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
suite.Keeper.SetAccount(suite.Ctx, *types.NewAccount( suite.Keeper.SetAccount(suite.Ctx, *types.NewAccount(
suite.Addrs[i], suite.Addrs[i],
keeper.ConversionMultiplier.QuoRaw(2), sdkmath.NewInt(10000000000),
)) ))
} }
suite.FundModuleAccountWithZgChain( suite.FundModuleAccountWithZgChain(
@ -97,7 +97,7 @@ func (suite *invariantTestSuite) SetupValidState() {
suite.NoError(err) suite.NoError(err)
} }
// RegisterRoutes implements sdk.InvariantRegistry // RegisterRoute implements sdk.InvariantRegistry
func (suite *invariantTestSuite) RegisterRoute(moduleName string, route string, invariant sdk.Invariant) { func (suite *invariantTestSuite) RegisterRoute(moduleName string, route string, invariant sdk.Invariant) {
_, exists := suite.invariants[moduleName] _, exists := suite.invariants[moduleName]
@ -132,45 +132,6 @@ func (suite *invariantTestSuite) runInvariant(route string, invariant func(bankK
return dMessage, dBroken return dMessage, dBroken
} }
func (suite *invariantTestSuite) TestFullyBackedInvariant() {
// default state is valid
_, broken := suite.runInvariant("fully-backed", keeper.FullyBackedInvariant)
suite.Equal(false, broken)
suite.SetupValidState()
_, broken = suite.runInvariant("fully-backed", keeper.FullyBackedInvariant)
suite.Equal(false, broken)
// break invariant by increasing total minor balances above module balance
suite.Keeper.AddBalance(suite.Ctx, suite.Addrs[0], sdk.OneInt())
message, broken := suite.runInvariant("fully-backed", keeper.FullyBackedInvariant)
suite.Equal("evmutil: fully backed broken invariant\nsum of minor balances greater than module account\n", message)
suite.Equal(true, broken)
}
func (suite *invariantTestSuite) TestSmallBalances() {
// default state is valid
_, broken := suite.runInvariant("small-balances", keeper.SmallBalancesInvariant)
suite.Equal(false, broken)
suite.SetupValidState()
_, broken = suite.runInvariant("small-balances", keeper.SmallBalancesInvariant)
suite.Equal(false, broken)
// increase minor balance at least above conversion multiplier
suite.Keeper.AddBalance(suite.Ctx, suite.Addrs[0], keeper.ConversionMultiplier)
// add same number of gas denom to avoid breaking other invariants
amt := sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 1))
suite.Require().NoError(
suite.App.FundModuleAccount(suite.Ctx, types.ModuleName, amt),
)
message, broken := suite.runInvariant("small-balances", keeper.SmallBalancesInvariant)
suite.Equal("evmutil: small balances broken invariant\nminor balances not all less than overflow\n", message)
suite.Equal(true, broken)
}
// the cosmos-coins-fully-backed invariant depends on 1-to-1 mapping of module balance to erc20s // the cosmos-coins-fully-backed invariant depends on 1-to-1 mapping of module balance to erc20s
// if coins can be sent directly to the module account, this assumption is broken. // if coins can be sent directly to the module account, this assumption is broken.
// this test verifies that coins cannot be directly sent to the module account. // this test verifies that coins cannot be directly sent to the module account.

View File

@ -4,34 +4,6 @@ order: 1
# Concepts # Concepts
## EVM Gas Denom
In order to use the EVM and be compatible with existing clients, the gas denom used by the EVM must be in 18 decimals. Since `ukava` has 6 decimals of precision, it cannot be used as the EVM gas denom directly.
To use the Kava token on the EVM, the evmutil module provides an `EvmBankKeeper` that is responsible for the conversion of `ukava` and `akava`. A user's excess `akava` balance is stored in the `x/evmutil` store, while its `ukava` balance remains in the cosmos-sdk `x/bank` module.
## `EvmBankKeeper` Overview
The `EvmBankKeeper` provides access to an account's total `akava` balance and the ability to transfer, mint, and burn `akava`. If anything other than the `akava` denom is requested, the `EvmBankKeeper` will panic.
This keeper implements the `x/evm` module's `BankKeeper` interface to enable the usage of `akava` denom on the EVM.
### `x/evm` Parameter Requirements
Since the EVM denom `akava` is required to use the `EvmBankKeeper`, it is necessary to set the `EVMDenom` param of the `x/evm` module to `akava`.
### Balance Calculation of `akava`
The `akava` balance of an account is derived from an account's **spendable** `ukava` balance times 10^12 (to derive its `akava` equivalent), plus the account's excess `akava` balance that can be accessed via the module `Keeper`.
### `akava` <> `ukava` Conversion
When an account does not have sufficient `akava` to cover a transfer or burn, the `EvmBankKeeper` will try to swap 1 `ukava` to its equivalent `akava` amount. It does this by transferring 1 `ukava` from the sender to the `x/evmutil` module account, then adding the equivalent `akava` amount to the sender's balance in the module state.
In reverse, if an account has enough `akava` balance for one or more `ukava`, the excess `akava` balance will be converted to `ukava`. This is done by removing the excess `akava` balance in the module store, then transferring the equivalent `ukava` coins from the `x/evmutil` module account to the target account.
The swap logic ensures that all `akava` is backed by the equivalent `ukava` balance stored in the module account.
## ERC20 token <> sdk.Coin Conversion ## ERC20 token <> sdk.Coin Conversion
`x/evmutil` facilitates moving assets between Kava's EVM and Cosmos co-chains. This must be handled differently depending on which co-chain to which the asset it native. The messages controlling these flows involve two accounts: `x/evmutil` facilitates moving assets between Kava's EVM and Cosmos co-chains. This must be handled differently depending on which co-chain to which the asset it native. The messages controlling these flows involve two accounts:
@ -46,7 +18,7 @@ When converting assets from the Cosmos co-chain to the EVM, the initiator is a `
`sdk.Coin`s native to the Cosmos co-chain can be converted to an ERC-20 representing the coin in the EVM. This works by transferring the coin from the initiator to `x/evmutil`'s module account and then minting an ERC-20 token to the receiver. Converting back, the initiator's ERC-20 representation of the coin is burned and the original Cosmos-native asset is transferred to the receiver. `sdk.Coin`s native to the Cosmos co-chain can be converted to an ERC-20 representing the coin in the EVM. This works by transferring the coin from the initiator to `x/evmutil`'s module account and then minting an ERC-20 token to the receiver. Converting back, the initiator's ERC-20 representation of the coin is burned and the original Cosmos-native asset is transferred to the receiver.
Cosmos-native asset converstion is done through the use of the `MsgConvertCosmosCoinToERC20` & `MsgConvertCosmosCoinFromERC20` messages (see **[Messages](03_messages.md)**). Cosmos-native asset conversion is done through the use of the `MsgConvertCosmosCoinToERC20` & `MsgConvertCosmosCoinFromERC20` messages (see **[Messages](03_messages.md)**).
Only Cosmos co-chain denominations that are in the `AllowedCosmosDenoms` param (see **[Params](05_params.md)**) can be converted via these messages. Only Cosmos co-chain denominations that are in the `AllowedCosmosDenoms` param (see **[Params](05_params.md)**) can be converted via these messages.
@ -65,7 +37,3 @@ EVM-native asset conversion is done through the use of the `MsgConvertERC20ToCoi
Only ERC20 contract address that are in the `EnabledConversionPairs` param (see **[Params](05_params.md)**) can be converted via these messages. Only ERC20 contract address that are in the `EnabledConversionPairs` param (see **[Params](05_params.md)**) can be converted via these messages.
`EnabledConversionPairs` can be altered through governance. `EnabledConversionPairs` can be altered through governance.
## Module Keeper
The module Keeper provides access to an account's excess `akava` balance and the ability to update the balance.

View File

@ -51,24 +51,12 @@ message AllowedCosmosCoinERC20Token {
```protobuf ```protobuf
message GenesisState { message GenesisState {
repeated Account accounts = 1 [(gogoproto.nullable) = false]; // previously stored accounts containing fractional balances.
reserved 1;
Params params = 2 [(gogoproto.nullable) = false]; Params params = 2 [(gogoproto.nullable) = false];
} }
``` ```
## Account
An `Account` is a struct representing the excess `akava` balance of an address.
Since an address's total `akava` balance is derived from its `ukava` balance and the excess `akava` balance stored by the `Account` struct, the `akava` balance here should never exceed 1 `ukava` (10^12 `akava`).
```protobuf
message Account {
bytes address = 1;
string balance = 2;
}
```
## Deployed Cosmos Coin Contract Addresses ## Deployed Cosmos Coin Contract Addresses
Addresses for the ERC20 contracts representing cosmos-sdk `Coin`s are kept in the module store. They are stored as bytes by the cosmos-sdk denom they represent. Addresses for the ERC20 contracts representing cosmos-sdk `Coin`s are kept in the module store. They are stored as bytes by the cosmos-sdk denom they represent.

View File

@ -21,13 +21,6 @@ parent:
The evmutil module provides additional functionalities on top of the evm module. The evmutil module provides additional functionalities on top of the evm module.
### EVM `akava` Usage
evmutil stores additional state data for evm accounts and exposes an `EvmBankKeeper` that should be used by the `x/evm` keeper for bank operations.
The purpose of the `EvmBankKeeper` is to allow the usage of the `akava` balance on the EVM via an account's existing `ukava` balance. This is needed because the EVM gas token use 18 decimals, and since `ukava` has 6 decimals, it cannot be used as the EVM gas denom directly.
For additional details on how balance conversions work, see **[Concepts](01_concepts.md)**.
### ERC20 Token <> sdk.Coin Conversion ### ERC20 Token <> sdk.Coin Conversion
evmutil exposes messages to allow for the conversion of Kava ERC20 tokens and sdk.Coins via a whitelist. evmutil exposes messages to allow for the conversion of Kava ERC20 tokens and sdk.Coins via a whitelist.

View File

@ -51,7 +51,6 @@ type Suite struct {
BankKeeper bankkeeper.Keeper BankKeeper bankkeeper.Keeper
AccountKeeper authkeeper.AccountKeeper AccountKeeper authkeeper.AccountKeeper
Keeper keeper.Keeper Keeper keeper.Keeper
EvmBankKeeper keeper.EvmBankKeeper
Addrs []sdk.AccAddress Addrs []sdk.AccAddress
EvmModuleAddr sdk.AccAddress EvmModuleAddr sdk.AccAddress
QueryClient types.QueryClient QueryClient types.QueryClient
@ -69,7 +68,6 @@ func (suite *Suite) SetupTest() {
suite.BankKeeper = tApp.GetBankKeeper() suite.BankKeeper = tApp.GetBankKeeper()
suite.AccountKeeper = tApp.GetAccountKeeper() suite.AccountKeeper = tApp.GetAccountKeeper()
suite.Keeper = tApp.GetEvmutilKeeper() suite.Keeper = tApp.GetEvmutilKeeper()
suite.EvmBankKeeper = keeper.NewEvmBankKeeper(tApp.GetEvmutilKeeper(), suite.BankKeeper, suite.AccountKeeper)
suite.EvmModuleAddr = suite.AccountKeeper.GetModuleAddress(evmtypes.ModuleName) suite.EvmModuleAddr = suite.AccountKeeper.GetModuleAddress(evmtypes.ModuleName)
// test evm user keys that have no minting permissions // test evm user keys that have no minting permissions

Some files were not shown because too many files have changed in this diff Show More