mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-24 23:35:19 +00:00
Merge pull request #74 from 0g-wh/dev
Some checks failed
Continuous Integration (Commit) / lint (push) Has been cancelled
Some checks failed
Continuous Integration (Commit) / lint (push) Has been cancelled
rebase to kava 0.27
This commit is contained in:
commit
a1dc4a4a77
@ -11,5 +11,10 @@ docs/
|
||||
networks/
|
||||
scratch/
|
||||
|
||||
# Ignore build cache directories to avoid
|
||||
# errors when addings these to docker images
|
||||
build/.cache
|
||||
build/.golangci-lint
|
||||
|
||||
go.work
|
||||
go.work.sum
|
||||
|
3
.github/CODEOWNERS
vendored
Normal file
3
.github/CODEOWNERS
vendored
Normal 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
|
57
.github/scripts/seed-internal-testnet.sh
vendored
57
.github/scripts/seed-internal-testnet.sh
vendored
@ -83,6 +83,31 @@ TETHER_USDT_CONTRACT_DEPLOY=$(npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NA
|
||||
TETHER_USDT_CONTRACT_ADDRESS=${TETHER_USDT_CONTRACT_DEPLOY: -42}
|
||||
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
|
||||
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
|
||||
@ -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 "$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 "$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
|
||||
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
|
||||
@ -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 "$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 "$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
|
||||
|
||||
@ -138,7 +173,7 @@ PARAM_CHANGE_PROP_TEMPLATE=$(
|
||||
{
|
||||
"subspace": "evmutil",
|
||||
"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/wETH_CONTRACT_ADDRESS/$wETH_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
|
||||
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)
|
||||
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.
|
||||
# convert 1 HARD to an erc20. doing this ensures the contract is deployed.
|
||||
kava tx evmutil convert-cosmos-coin-to-erc20 \
|
||||
|
@ -67,7 +67,6 @@ jobs:
|
||||
--update-playbook-filename=$PLAYBOOK_NAME \
|
||||
--chain-id=$CHAIN_ID \
|
||||
--max-upgrade-batch-size=0 \
|
||||
--node-states=Standby \
|
||||
--wait-for-node-sync-after-upgrade=false
|
||||
env:
|
||||
SSM_DOCUMENT_NAME: ${{ inputs.ssm-document-name }}
|
||||
|
12
.github/workflows/cd-seed-chain.yml
vendored
12
.github/workflows/cd-seed-chain.yml
vendored
@ -35,12 +35,16 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
- name: checkout version of kava used by network
|
||||
- name: get desired version of network
|
||||
id: kava-version
|
||||
run: |
|
||||
git pull -p
|
||||
git checkout $(cat ${KAVA_VERSION_FILEPATH})
|
||||
echo "KAVA_VERSION=$(cat ./ci/env/kava-internal-testnet/KAVA.VERSION)" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
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
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
@ -68,7 +72,7 @@ jobs:
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
cache: npm
|
||||
node-version: 18
|
||||
node-version-file: .tool-versions
|
||||
cache-dependency-path: kava-bridge/contract/package.json
|
||||
- name: "install ERC20 contract deployment dependencies"
|
||||
run: "npm install"
|
||||
|
1
.github/workflows/cd-start-chain.yml
vendored
1
.github/workflows/cd-start-chain.yml
vendored
@ -63,7 +63,6 @@ jobs:
|
||||
--update-playbook-filename=$PLAYBOOK_NAME \
|
||||
--chain-id=$CHAIN_ID \
|
||||
--max-upgrade-batch-size=0 \
|
||||
--node-states=Standby \
|
||||
--wait-for-node-sync-after-upgrade=true
|
||||
env:
|
||||
SSM_DOCUMENT_NAME: ${{ inputs.ssm-document-name }}
|
||||
|
39
.github/workflows/ci-default.yml
vendored
39
.github/workflows/ci-default.yml
vendored
@ -35,6 +35,35 @@ jobs:
|
||||
run: make test
|
||||
- name: run e2e tests
|
||||
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:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -44,16 +73,10 @@ jobs:
|
||||
id: kava-version
|
||||
run: |
|
||||
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
|
||||
with:
|
||||
ref: master
|
||||
- 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 }}
|
||||
ref: ${{ steps.kava-version.outputs.KAVA_VERSION }}
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
|
22
.github/workflows/ci-docker.yml
vendored
22
.github/workflows/ci-docker.yml
vendored
@ -50,6 +50,17 @@ jobs:
|
||||
username: ${{ inputs.dockerhub-username }}
|
||||
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
|
||||
- name: Build and push (goleveldb)
|
||||
uses: docker/build-push-action@v5
|
||||
@ -89,6 +100,17 @@ jobs:
|
||||
username: ${{ inputs.dockerhub-username }}
|
||||
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
|
||||
- name: Build and push (rocksdb)
|
||||
uses: docker/build-push-action@v5
|
||||
|
26
.github/workflows/ci-lint.yml
vendored
26
.github/workflows/ci-lint.yml
vendored
@ -7,11 +7,25 @@ jobs:
|
||||
uses: ./.github/workflows/proto.yml
|
||||
golangci-lint:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
checks: write # allow write access to checks to allow the action to annotate code in the PR.
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: golangci-lint
|
||||
uses: reviewdog/action-golangci-lint@v2
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with: { fetch-depth: 0 }
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
github_token: ${{ secrets.github_token }}
|
||||
reporter: github-pr-review
|
||||
golangci_lint_flags: --timeout 10m
|
||||
go-version-file: go.mod
|
||||
- name: Load Version
|
||||
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 }}
|
||||
|
3
.github/workflows/ci-master.yml
vendored
3
.github/workflows/ci-master.yml
vendored
@ -45,6 +45,9 @@ jobs:
|
||||
dockerhub-username: kavaops
|
||||
extra-image-tag: master
|
||||
secrets: inherit
|
||||
rosetta:
|
||||
uses: ./.github/workflows/ci-rosetta.yml
|
||||
secrets: inherit
|
||||
post-pipeline-metrics:
|
||||
uses: ./.github/workflows/metric-pipeline.yml
|
||||
if: always() # always run so we metric failures and successes
|
||||
|
27
.github/workflows/ci-pr-lint.yml
vendored
Normal file
27
.github/workflows/ci-pr-lint.yml
vendored
Normal 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 }}
|
5
.github/workflows/ci-release.yml
vendored
5
.github/workflows/ci-release.yml
vendored
@ -4,9 +4,6 @@ on:
|
||||
tags:
|
||||
- "v[0-9]+.[0-9]+.[0-9]+*"
|
||||
jobs:
|
||||
# run per commit ci checks against released version
|
||||
lint-checks:
|
||||
uses: ./.github/workflows/ci-lint.yml
|
||||
# run default ci checks against released version
|
||||
default-checks:
|
||||
uses: ./.github/workflows/ci-default.yml
|
||||
@ -14,7 +11,7 @@ jobs:
|
||||
# get the version tag that triggered this workflow
|
||||
get-version-tag:
|
||||
# prep version release only if all checks pass
|
||||
needs: [lint-checks, default-checks]
|
||||
needs: default-checks
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
git-tag: ${{ steps.git-tag.outputs.tag }}
|
||||
|
22
.github/workflows/ci-rocksdb-build.yml
vendored
22
.github/workflows/ci-rocksdb-build.yml
vendored
@ -19,25 +19,3 @@ jobs:
|
||||
run: bash ${GITHUB_WORKSPACE}/.github/scripts/install-rocksdb.sh
|
||||
- name: build application
|
||||
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
16
.github/workflows/ci-rosetta.yml
vendored
Normal 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
3
.gitignore
vendored
@ -31,6 +31,9 @@ out
|
||||
# Ignore build cache dir
|
||||
build/.cache
|
||||
|
||||
# Ignore make lint cache
|
||||
build/.golangci-lint
|
||||
|
||||
# Ignore installed binaires
|
||||
build/bin
|
||||
|
||||
|
1
.golangci-version
Normal file
1
.golangci-version
Normal file
@ -0,0 +1 @@
|
||||
v1.59
|
130
.golangci.yml
Normal file
130
.golangci.yml
Normal 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
16
.mockery.yaml
Normal 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:
|
@ -1,2 +1,2 @@
|
||||
golang 1.21
|
||||
nodejs 18.16.0
|
||||
golang 1.21.9
|
||||
nodejs 20.16.0
|
||||
|
19
CHANGELOG.md
19
CHANGELOG.md
@ -38,6 +38,16 @@ Ref: https://keepachangelog.com/en/1.0.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
|
||||
|
||||
- (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
|
||||
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
|
||||
[#1848]: https://github.com/Kava-Labs/kava/pull/1848
|
||||
[#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
|
||||
[#751]: https://github.com/Kava-Labs/kava/pull/751
|
||||
[#780]: https://github.com/Kava-Labs/kava/pull/780
|
||||
[unreleased]: https://github.com/Kava-Labs/kava/compare/v0.25.0...HEAD
|
||||
[v0.25.0]: https://github.com/Kava-Labs/kava/compare/v0.25.0...v0.24.3
|
||||
[unreleased]: https://github.com/Kava-Labs/kava/compare/v0.26.0...HEAD
|
||||
[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.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
|
||||
|
@ -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 \
|
||||
&& 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
|
||||
RUN apt-get update
|
||||
|
||||
WORKDIR /root/0gchain
|
||||
# Copy dependency files first to facilitate dependency caching
|
||||
|
22
Dockerfile-rocksdb-base
Normal file
22
Dockerfile-rocksdb-base
Normal 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
|
49
Makefile
49
Makefile
@ -105,6 +105,8 @@ include $(BUILD_DIR)/deps.mk
|
||||
include $(BUILD_DIR)/proto.mk
|
||||
include $(BUILD_DIR)/proto-deps.mk
|
||||
|
||||
include $(BUILD_DIR)/lint.mk
|
||||
|
||||
#export GO111MODULE = on
|
||||
# process build tags
|
||||
build_tags = netgo
|
||||
@ -208,6 +210,14 @@ build-release: go.sum
|
||||
build-linux: go.sum
|
||||
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
|
||||
$(GO_BIN) install -mod=readonly $(BUILD_FLAGS) $(MAIN_ENTRY)
|
||||
|
||||
@ -234,13 +244,6 @@ link-check:
|
||||
# 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*"
|
||||
|
||||
|
||||
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:
|
||||
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
|
||||
@ -265,11 +268,11 @@ build-docker-local-0gchain:
|
||||
|
||||
# Run a 4-node testnet locally
|
||||
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
|
||||
docker-compose up -d
|
||||
@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
|
||||
|
||||
localnet-stop:
|
||||
docker-compose down
|
||||
$(DOCKER) compose down
|
||||
|
||||
# Launch a new single validator chain
|
||||
start:
|
||||
@ -311,12 +314,14 @@ test-basic: test
|
||||
test-e2e: docker-build
|
||||
$(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:
|
||||
@$(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
|
||||
# `-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.
|
||||
@ -327,6 +332,18 @@ test-cli: build
|
||||
test-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.
|
||||
# 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:
|
||||
@ -337,14 +354,14 @@ start-remote-sims:
|
||||
# submit an array job on AWS Batch, using 1000 seeds, spot instances
|
||||
aws batch submit-job \
|
||||
-—job-name "master-$(VERSION)" \
|
||||
-—job-queue “simulation-1-queue-spot" \
|
||||
-—job-queue "simulation-1-queue-spot" \
|
||||
-—array-properties size=1000 \
|
||||
-—job-definition $(BINARY_NAME)-sim-master \
|
||||
-—container-override environment=[{SIM_NAME=master-$(VERSION)}]
|
||||
|
||||
update-kvtool:
|
||||
git submodule init || true
|
||||
git submodule update
|
||||
git submodule update --remote
|
||||
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
|
||||
|
@ -17,13 +17,13 @@ Reference implementation of 0G Chain, the first modular AI chain. Built using th
|
||||
<!---
|
||||
## 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
|
||||
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
|
||||
git checkout v0.25.0
|
||||
git checkout v0.26.2
|
||||
make install
|
||||
```
|
||||
|
||||
@ -49,7 +49,7 @@ If you have technical questions or concerns, ask a developer or community member
|
||||
|
||||
## 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
|
||||
|
||||
|
@ -405,7 +405,7 @@ func (suite *EIP712TestSuite) TestEIP712Tx() {
|
||||
// usdxToMintAmt: 99,
|
||||
// },
|
||||
{
|
||||
name: "fails when convertion more erc20 usdc than balance",
|
||||
name: "fails when conversion more erc20 usdc than balance",
|
||||
usdcDepositAmt: 51_000,
|
||||
usdxToMintAmt: 100,
|
||||
errMsg: "transfer amount exceeds balance",
|
||||
|
30
app/app.go
30
app/app.go
@ -95,6 +95,7 @@ import (
|
||||
ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper"
|
||||
solomachine "github.com/cosmos/ibc-go/v7/modules/light-clients/06-solomachine"
|
||||
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"
|
||||
ethermintconfig "github.com/evmos/ethermint/server/config"
|
||||
"github.com/evmos/ethermint/x/evm"
|
||||
@ -129,6 +130,9 @@ import (
|
||||
issuance "github.com/0glabs/0g-chain/x/issuance"
|
||||
issuancekeeper "github.com/0glabs/0g-chain/x/issuance/keeper"
|
||||
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"
|
||||
pricefeedkeeper "github.com/0glabs/0g-chain/x/pricefeed/keeper"
|
||||
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"
|
||||
validatorvestingtypes "github.com/0glabs/0g-chain/x/validator-vesting/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -178,6 +181,7 @@ var (
|
||||
validatorvesting.AppModuleBasic{},
|
||||
evmutil.AppModuleBasic{},
|
||||
mint.AppModuleBasic{},
|
||||
precisebank.AppModuleBasic{},
|
||||
council.AppModuleBasic{},
|
||||
dasigners.AppModuleBasic{},
|
||||
consensus.AppModuleBasic{},
|
||||
@ -199,6 +203,7 @@ var (
|
||||
issuancetypes.ModuleAccountName: {authtypes.Minter, authtypes.Burner},
|
||||
bep3types.ModuleName: {authtypes.Burner, 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
|
||||
dasignersKeeper dasignerskeeper.Keeper
|
||||
consensusParamsKeeper consensusparamkeeper.Keeper
|
||||
precisebankKeeper precisebankkeeper.Keeper
|
||||
|
||||
// make scoped keepers public for test purposes
|
||||
ScopedIBCKeeper capabilitykeeper.ScopedKeeper
|
||||
@ -318,7 +324,7 @@ func NewApp(
|
||||
counciltypes.StoreKey,
|
||||
dasignerstypes.StoreKey,
|
||||
vestingtypes.StoreKey,
|
||||
consensusparamtypes.StoreKey, crisistypes.StoreKey,
|
||||
consensusparamtypes.StoreKey, crisistypes.StoreKey, precisebanktypes.StoreKey,
|
||||
ibcwasmtypes.StoreKey,
|
||||
)
|
||||
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey)
|
||||
@ -482,7 +488,13 @@ func NewApp(
|
||||
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
|
||||
app.dasignersKeeper = dasignerskeeper.NewKeeper(keys[dasignerstypes.StoreKey], appCodec, app.stakingKeeper, govAuthAddrStr)
|
||||
// precopmiles
|
||||
@ -492,16 +504,18 @@ func NewApp(
|
||||
panic("initialize precompile failed")
|
||||
}
|
||||
precompiles[daSignersPrecompile.Address()] = daSignersPrecompile
|
||||
// evm keeper
|
||||
|
||||
app.evmKeeper = evmkeeper.NewKeeper(
|
||||
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey],
|
||||
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,
|
||||
evmSubspace,
|
||||
precompiles,
|
||||
)
|
||||
|
||||
app.evmutilKeeper.SetEvmKeeper(app.evmKeeper)
|
||||
|
||||
// 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),
|
||||
// nil InflationCalculationFn, use SDK's default inflation function
|
||||
mint.NewAppModule(appCodec, app.mintKeeper, app.accountKeeper, nil, mintSubspace),
|
||||
precisebank.NewAppModule(app.precisebankKeeper, app.bankKeeper, app.accountKeeper),
|
||||
council.NewAppModule(app.CouncilKeeper),
|
||||
ibcwasm.NewAppModule(app.ibcWasmClientKeeper),
|
||||
dasigners.NewAppModule(app.dasignersKeeper, *app.stakingKeeper),
|
||||
@ -716,6 +731,7 @@ func NewApp(
|
||||
counciltypes.ModuleName,
|
||||
consensusparamtypes.ModuleName,
|
||||
packetforwardtypes.ModuleName,
|
||||
precisebanktypes.ModuleName,
|
||||
ibcwasmtypes.ModuleName,
|
||||
dasignerstypes.ModuleName,
|
||||
)
|
||||
@ -752,6 +768,7 @@ func NewApp(
|
||||
counciltypes.ModuleName,
|
||||
consensusparamtypes.ModuleName,
|
||||
packetforwardtypes.ModuleName,
|
||||
precisebanktypes.ModuleName,
|
||||
ibcwasmtypes.ModuleName,
|
||||
dasignerstypes.ModuleName,
|
||||
)
|
||||
@ -786,6 +803,7 @@ func NewApp(
|
||||
counciltypes.ModuleName,
|
||||
consensusparamtypes.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
|
||||
ibcwasmtypes.ModuleName,
|
||||
dasignerstypes.ModuleName,
|
||||
|
@ -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
|
||||
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:
|
||||
|
||||
{
|
||||
|
@ -130,7 +130,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() {
|
||||
|
||||
passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal)
|
||||
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.SetupTest()
|
||||
@ -145,7 +145,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() {
|
||||
|
||||
passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal)
|
||||
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.SetupTest()
|
||||
@ -162,7 +162,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() {
|
||||
|
||||
passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal)
|
||||
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.SetupTest()
|
||||
@ -179,7 +179,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() {
|
||||
|
||||
passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal)
|
||||
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.SetupTest()
|
||||
@ -191,7 +191,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() {
|
||||
|
||||
passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal)
|
||||
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.SetupTest()
|
||||
@ -204,7 +204,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() {
|
||||
|
||||
passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal)
|
||||
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)
|
||||
})
|
||||
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ import (
|
||||
committeekeeper "github.com/0glabs/0g-chain/x/committee/keeper"
|
||||
evmutilkeeper "github.com/0glabs/0g-chain/x/evmutil/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"
|
||||
)
|
||||
|
||||
@ -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) GetFeeMarketKeeper() feemarketkeeper.Keeper { return tApp.feeMarketKeeper }
|
||||
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 {
|
||||
return tApp.keys[key]
|
||||
}
|
||||
|
||||
func (tApp TestApp) GetBlockedMaccAddrs() map[string]bool {
|
||||
return tApp.loadBlockedMaccAddrs()
|
||||
}
|
||||
|
||||
// LegacyAmino returns the app's amino codec.
|
||||
func (app *App) LegacyAmino() *codec.LegacyAmino {
|
||||
return app.legacyAmino
|
||||
@ -465,7 +471,7 @@ func (tApp TestApp) SetInflation(ctx sdk.Context, value sdk.Dec) {
|
||||
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) {
|
||||
r := rand.New(rand.NewSource(12345)) // make the generation deterministic
|
||||
keys = make([]cryptotypes.PrivKey, n)
|
||||
|
240
app/upgrades.go
240
app/upgrades.go
@ -3,13 +3,21 @@ package app
|
||||
import (
|
||||
"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"
|
||||
"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"
|
||||
)
|
||||
|
||||
const (
|
||||
UpgradeName_Testnet = "v0.3.1"
|
||||
UpgradeName_Testnet = "v0.4.0"
|
||||
)
|
||||
|
||||
// RegisterUpgradeHandlers registers the upgrade handlers for the app.
|
||||
@ -18,6 +26,24 @@ func (app App) RegisterUpgradeHandlers() {
|
||||
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.
|
||||
@ -30,13 +56,213 @@ func upgradeHandler(
|
||||
plan upgradetypes.Plan,
|
||||
fromVM module.VersionMap,
|
||||
) (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)
|
||||
params.MintDenom = "ua0gi"
|
||||
app.mintKeeper.SetParams(ctx, params)
|
||||
// Run migrations for all modules and return new consensus version map.
|
||||
versionMap, err := app.mm.RunMigrations(ctx, app.configurator, fromVM)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// run migrations for all modules and return new consensus version map
|
||||
return app.mm.RunMigrations(ctx, app.configurator, fromVM)
|
||||
logger.Info("completed store migrations")
|
||||
|
||||
// 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
434
app/upgrades_test.go
Normal 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
45
build/lint.mk
Normal 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 $@
|
@ -56,6 +56,7 @@ proto-update-deps: check-rsync ## Update all third party proto files
|
||||
@mkdir -p client/docs
|
||||
@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 $(ETHERMINT_PATH)/client/docs/swagger-ui/swagger.yaml client/docs/ethermint-swagger.yml
|
||||
|
||||
@mkdir -p $(COSMOS_PROTO_TYPES)
|
||||
@cp -f $(COSMOS_PROTO_PATH)/proto/cosmos_proto/cosmos.proto $(COSMOS_PROTO_TYPES)/cosmos.proto
|
||||
|
2
ci/env/kava-internal-testnet/KAVA.VERSION
vendored
2
ci/env/kava-internal-testnet/KAVA.VERSION
vendored
@ -1 +1 @@
|
||||
a967d2fdda299ec8e1e3b99fb55bd06ecfdb0469
|
||||
6862cde560c70cb82f7908e6cef22ca223465bd2
|
||||
|
124
ci/env/kava-internal-testnet/genesis.json
vendored
124
ci/env/kava-internal-testnet/genesis.json
vendored
@ -22,6 +22,8 @@
|
||||
},
|
||||
"app_hash": "",
|
||||
"app_state": {
|
||||
"06-solomachine": null,
|
||||
"07-tendermint": null,
|
||||
"auction": {
|
||||
"next_auction_id": "1",
|
||||
"params": {
|
||||
@ -505,6 +507,10 @@
|
||||
{
|
||||
"address": "kava1vlpsrmdyuywvaqrv7rx6xga224sqfwz3fyfhwq",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "bnb",
|
||||
"amount": "500000000"
|
||||
},
|
||||
{
|
||||
"denom": "btcb",
|
||||
"amount": "200000000"
|
||||
@ -525,6 +531,10 @@
|
||||
"denom": "erc20/axelar/wbtc",
|
||||
"amount": "1000000000"
|
||||
},
|
||||
{
|
||||
"denom": "erc20/bitgo/wbtc",
|
||||
"amount": "200000000"
|
||||
},
|
||||
{
|
||||
"denom": "erc20/multichain/usdc",
|
||||
"amount": "1000000000000000000"
|
||||
@ -556,12 +566,20 @@
|
||||
{
|
||||
"denom": "usdx",
|
||||
"amount": "103000000000"
|
||||
},
|
||||
{
|
||||
"denom": "xrpb",
|
||||
"amount": "1000000000000000"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": "kava1krh7k30pc9rteejpl2zycj0vau58y8c69xkzws",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "bnb",
|
||||
"amount": "100000000000000000"
|
||||
},
|
||||
{
|
||||
"denom": "btcb",
|
||||
"amount": "200000000"
|
||||
@ -582,6 +600,10 @@
|
||||
"denom": "erc20/axelar/wbtc",
|
||||
"amount": "1000000000"
|
||||
},
|
||||
{
|
||||
"denom": "erc20/bitgo/wbtc",
|
||||
"amount": "200000000"
|
||||
},
|
||||
{
|
||||
"denom": "erc20/tether/usdt",
|
||||
"amount": "100000000000"
|
||||
@ -601,6 +623,10 @@
|
||||
{
|
||||
"denom": "usdx",
|
||||
"amount": "103000000000"
|
||||
},
|
||||
{
|
||||
"denom": "xrpb",
|
||||
"amount": "103000000000"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -822,6 +848,7 @@
|
||||
"gov_denom": "ukava",
|
||||
"params": {
|
||||
"circuit_breaker": false,
|
||||
"liquidation_block_interval": 500,
|
||||
"collateral_params": [
|
||||
{
|
||||
"denom": "bnb",
|
||||
@ -993,8 +1020,7 @@
|
||||
"check_collateralization_index_count": "10",
|
||||
"conversion_factor": "6"
|
||||
}
|
||||
]
|
||||
,
|
||||
],
|
||||
"debt_auction_lot": "10000000000",
|
||||
"debt_auction_threshold": "100000000000",
|
||||
"debt_param": {
|
||||
@ -1241,7 +1267,15 @@
|
||||
"votes": []
|
||||
},
|
||||
"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": {
|
||||
"constant_fee": {
|
||||
@ -2067,6 +2101,25 @@
|
||||
}
|
||||
],
|
||||
"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
|
||||
@ -2229,22 +2282,27 @@
|
||||
"deposits": [],
|
||||
"votes": [],
|
||||
"proposals": [],
|
||||
"deposit_params": {
|
||||
"deposit_params": null,
|
||||
"voting_params": {
|
||||
"voting_period": "604800s"
|
||||
},
|
||||
"tally_params": null,
|
||||
"params": {
|
||||
"min_deposit": [
|
||||
{
|
||||
"denom": "ukava",
|
||||
"amount": "10000000"
|
||||
}
|
||||
],
|
||||
"max_deposit_period": "172800s"
|
||||
},
|
||||
"voting_params": {
|
||||
"voting_period": "600s"
|
||||
},
|
||||
"tally_params": {
|
||||
"max_deposit_period": "172800s",
|
||||
"voting_period": "604800s",
|
||||
"quorum": "0.334000000000000000",
|
||||
"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": {
|
||||
@ -2519,6 +2577,24 @@
|
||||
},
|
||||
"reserve_factor": "0.025000000000000000",
|
||||
"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"
|
||||
@ -2734,6 +2810,18 @@
|
||||
"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": [],
|
||||
@ -3170,6 +3258,16 @@
|
||||
}
|
||||
},
|
||||
"params": null,
|
||||
"packetfowardmiddleware": {
|
||||
"params": {
|
||||
"fee_percentage": "0.000000000000000000"
|
||||
},
|
||||
"in_flight_packets": {}
|
||||
},
|
||||
"precisebank": {
|
||||
"balances": [],
|
||||
"remainder": "0"
|
||||
},
|
||||
"pricefeed": {
|
||||
"params": {
|
||||
"markets": [
|
||||
@ -3643,6 +3741,7 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"router": {},
|
||||
"savings": {
|
||||
"params": {
|
||||
"supported_denoms": [
|
||||
@ -3814,7 +3913,8 @@
|
||||
"params": {
|
||||
"send_enabled": true,
|
||||
"receive_enabled": true
|
||||
}
|
||||
},
|
||||
"total_escrowed": []
|
||||
},
|
||||
"upgrade": {},
|
||||
"validatorvesting": null,
|
||||
|
3
ci/env/kava-protonet/genesis.json
vendored
3
ci/env/kava-protonet/genesis.json
vendored
@ -3006,6 +3006,9 @@
|
||||
},
|
||||
"in_flight_packets": {}
|
||||
},
|
||||
"precisebank": {
|
||||
"remainder": "0"
|
||||
},
|
||||
"pricefeed": {
|
||||
"params": {
|
||||
"markets": [
|
||||
|
@ -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",
|
||||
"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",
|
||||
"dereference": {
|
||||
|
4458
client/docs/ethermint-swagger.yml
Normal file
4458
client/docs/ethermint-swagger.yml
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
381
client/erc20/MintableBurnableERC20.abi
Normal file
381
client/erc20/MintableBurnableERC20.abi
Normal 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"
|
||||
}
|
||||
]
|
1
client/erc20/MintableBurnableERC20.bin
Normal file
1
client/erc20/MintableBurnableERC20.bin
Normal file
File diff suppressed because one or more lines are too long
1069
client/erc20/main.go
Normal file
1069
client/erc20/main.go
Normal file
File diff suppressed because one or more lines are too long
@ -6,6 +6,8 @@ import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/0glabs/0g-chain/app"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
grpcConn, err := grpc.DialContext(ctx, grpcUrl.Host, secureOpt)
|
||||
grpcConn, err := grpc.DialContext(
|
||||
ctx,
|
||||
grpcUrl.Host,
|
||||
secureOpt,
|
||||
grpc.WithDefaultCallOptions(grpc.ForceCodec(grpcCodec)),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import (
|
||||
committeetypes "github.com/0glabs/0g-chain/x/committee/types"
|
||||
evmutiltypes "github.com/0glabs/0g-chain/x/evmutil/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"
|
||||
)
|
||||
|
||||
@ -65,6 +66,7 @@ type QueryClient struct {
|
||||
Evmutil evmutiltypes.QueryClient
|
||||
Issuance issuancetypes.QueryClient
|
||||
Pricefeed pricefeedtypes.QueryClient
|
||||
Precisebank precisebanktypes.QueryClient
|
||||
}
|
||||
|
||||
// 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),
|
||||
Issuance: issuancetypes.NewQueryClient(conn),
|
||||
Pricefeed: pricefeedtypes.NewQueryClient(conn),
|
||||
Precisebank: precisebanktypes.NewQueryClient(conn),
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/Kava-Labs/opendb"
|
||||
cometbftdb "github.com/cometbft/cometbft-db"
|
||||
"github.com/cometbft/cometbft/libs/log"
|
||||
tmtypes "github.com/cometbft/cometbft/types"
|
||||
@ -63,7 +64,7 @@ func (ac appCreator) newApp(
|
||||
|
||||
homeDir := cast.ToString(appOpts.Get(flags.FlagHome))
|
||||
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 {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -31,10 +31,7 @@ func newDataCmd(opts ethermintserver.StartOptions) *cobra.Command {
|
||||
}
|
||||
|
||||
printKeys(tree)
|
||||
hash, err := tree.Hash()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hash := tree.Hash()
|
||||
fmt.Printf("Hash: %X\n", hash)
|
||||
fmt.Printf("Size: %X\n", tree.Size())
|
||||
|
||||
|
@ -28,11 +28,7 @@ func newHashCmd(opts ethermintserver.StartOptions) *cobra.Command {
|
||||
return err
|
||||
}
|
||||
|
||||
hash, err := tree.Hash()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Hash: %X\n", hash)
|
||||
fmt.Printf("Hash: %X\n", tree.Hash())
|
||||
|
||||
return nil
|
||||
},
|
||||
|
@ -2,15 +2,19 @@ package iavlviewer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"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/server"
|
||||
"github.com/cosmos/cosmos-sdk/store/wrapper"
|
||||
ethermintserver "github.com/evmos/ethermint/server"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cosmos/iavl"
|
||||
iavldb "github.com/cosmos/iavl/db"
|
||||
)
|
||||
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
|
||||
tree, err := iavl.NewMutableTree(db, DefaultCacheSize, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tree := iavl.NewMutableTree(iavldb.NewWrapper(db), DefaultCacheSize, false, log.NewLogger(os.Stdout))
|
||||
ver, err := tree.LoadVersion(int64(version))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -14,14 +14,14 @@ import (
|
||||
"syscall"
|
||||
"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/server"
|
||||
"github.com/linxGnu/grocksdb"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/cometbft/cometbft/libs/log"
|
||||
"github.com/Kava-Labs/opendb"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -3,16 +3,18 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"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/config"
|
||||
"github.com/cosmos/cosmos-sdk/client/debug"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
|
||||
tmcfg "github.com/cometbft/cometbft/config"
|
||||
tmcli "github.com/cometbft/cometbft/libs/cli"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
@ -29,8 +31,8 @@ import (
|
||||
"github.com/0glabs/0g-chain/chaincfg"
|
||||
"github.com/0glabs/0g-chain/cmd/0gchaind/iavlviewer"
|
||||
"github.com/0glabs/0g-chain/cmd/0gchaind/rocksdb"
|
||||
"github.com/0glabs/0g-chain/cmd/opendb"
|
||||
"github.com/0glabs/0g-chain/crypto/vrf"
|
||||
"github.com/Kava-Labs/opendb"
|
||||
)
|
||||
|
||||
func customKeyringOptions() keyring.Option {
|
||||
@ -52,7 +54,7 @@ func NewRootCmd() *cobra.Command {
|
||||
WithAccountRetriever(types.AccountRetriever{}).
|
||||
WithBroadcastMode(flags.FlagBroadcastMode).
|
||||
WithHomeDir(chaincfg.DefaultNodeHome).
|
||||
WithKeyringOptions(customKeyringOptions()).
|
||||
WithKeyringOptions(hd.EthSecp256k1Option()).
|
||||
WithViper(chaincfg.EnvPrefix)
|
||||
rootCmd := &cobra.Command{
|
||||
Use: chaincfg.AppName,
|
||||
@ -90,7 +92,14 @@ func NewRootCmd() *cobra.Command {
|
||||
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) {
|
||||
gentxModule, ok := app.ModuleBasics[genutiltypes.ModuleName].(genutil.AppModuleBasic)
|
||||
if !ok {
|
||||
@ -120,7 +129,7 @@ func addSubCmds(rootCmd *cobra.Command, encodingConfig params.EncodingConfig, de
|
||||
opts := ethermintserver.StartOptions{
|
||||
AppCreator: ac.newApp,
|
||||
DefaultNodeHome: chaincfg.DefaultNodeHome,
|
||||
DBOpener: opendb.OpenDB,
|
||||
DBOpener: dbOpener,
|
||||
}
|
||||
// ethermintserver adds additional flags to start the JSON-RPC server for evm support
|
||||
ethermintserver.AddCommands(
|
||||
|
@ -219,11 +219,14 @@ func shardApplicationDb(multistore *rootmulti.Store, startBlock, endBlock int64)
|
||||
}
|
||||
|
||||
if len(pruneHeights) > 0 {
|
||||
// prune application state
|
||||
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 nil
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
@ -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)
|
||||
}
|
@ -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
|
||||
}
|
@ -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)
|
||||
}
|
@ -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
|
||||
}
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -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))
|
||||
}
|
2248
contracts/package-lock.json
generated
2248
contracts/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,7 @@
|
||||
"private": true,
|
||||
"description": "Solidity contracts for 0g Blockchain",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run clean && npm run compile && npm run ethermint-json",
|
||||
@ -23,14 +23,14 @@
|
||||
"test": "hardhat test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nomicfoundation/hardhat-toolbox": "^2.0.2",
|
||||
"@nomicfoundation/hardhat-toolbox": "^5.0.0",
|
||||
"@openzeppelin/contracts": "4.8.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.6",
|
||||
"@typescript-eslint/parser": "^5.59.6",
|
||||
"eslint": "^8.40.0",
|
||||
"eslint-config-prettier": "8.8.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"hardhat": "^2.14.0",
|
||||
"hardhat": "^2.22.8",
|
||||
"prettier": "2.8.8",
|
||||
"prettier-plugin-solidity": "^1.1.3",
|
||||
"solhint": "^3.4.1",
|
||||
|
@ -26,7 +26,7 @@ rm -rf $DATA
|
||||
|
||||
BINARY=kava
|
||||
|
||||
# Create new data directory, overwriting any that alread existed
|
||||
# Create new data directory, overwriting any that already existed
|
||||
chainID="kavalocalnet_8888-1"
|
||||
$BINARY init validator --chain-id $chainID
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
123
go.mod
123
go.mod
@ -4,61 +4,62 @@ go 1.21
|
||||
|
||||
require (
|
||||
cosmossdk.io/errors v1.0.1
|
||||
cosmossdk.io/log v1.3.1
|
||||
cosmossdk.io/math v1.3.0
|
||||
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/cometbft/cometbft v0.37.4
|
||||
github.com/cometbft/cometbft v0.37.9
|
||||
github.com/cometbft/cometbft-db v0.9.1
|
||||
github.com/coniks-sys/coniks-go v0.0.0-20180722014011-11acf4819b71
|
||||
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/go-bip39 v1.0.0
|
||||
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-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/ethereum/go-ethereum v1.10.26
|
||||
github.com/evmos/ethermint v0.21.0
|
||||
github.com/go-kit/kit v0.12.0
|
||||
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/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/prometheus/client_golang v1.14.0
|
||||
github.com/shopspring/decimal v1.4.0
|
||||
github.com/spf13/cast v1.6.0
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/spf13/viper v1.16.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/viper v1.18.2
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/subosito/gotenv v1.6.0
|
||||
golang.org/x/crypto v0.24.0
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0
|
||||
google.golang.org/grpc v1.60.1
|
||||
google.golang.org/protobuf v1.32.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de
|
||||
google.golang.org/grpc v1.63.2
|
||||
google.golang.org/protobuf v1.33.0
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.111.0 // indirect
|
||||
cloud.google.com/go/compute v1.23.3 // indirect
|
||||
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.5 // indirect
|
||||
cloud.google.com/go/storage v1.35.1 // 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/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.1 // indirect
|
||||
github.com/ChainSafe/go-schnorrkel v1.0.0 // 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/VictoriaMetrics/fastcache v1.6.0 // 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/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // 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/btcutil v1.1.3 // indirect
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
|
||||
github.com/btcsuite/btcd/btcutil v1.1.5 // indirect
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash 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/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/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 v0.7.9 // indirect
|
||||
github.com/confio/ics23/go v0.9.0 // indirect
|
||||
github.com/consensys/bavard v0.1.13 // indirect
|
||||
github.com/cosmos/btcutil v1.0.5 // indirect
|
||||
github.com/cosmos/gogogateway v1.2.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/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/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/dgraph-io/badger/v2 v2.2007.4 // 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/dvsekhvalnov/jose2go v1.6.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/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-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-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // 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/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/mock v1.6.0 // 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/orderedcode v0.0.1 // 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/gax-go/v2 v2.12.0 // 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/ristretto255 v0.1.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-safetemp v1.0.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/hdevalence/ed25519consensus v0.1.0 // 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/jmespath/go-jmespath v0.4.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/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/magiconair/properties v1.8.7 // indirect
|
||||
github.com/manifoldco/promptui v0.9.0 // 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/mtibben/percent v0.2.1 // 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/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/procfs v0.9.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/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/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/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // 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/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/numcpus v0.4.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
|
||||
go.etcd.io/bbolt v1.3.8 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/otel v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.19.0 // indirect
|
||||
golang.org/x/net v0.21.0 // indirect
|
||||
golang.org/x/oauth2 v0.15.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/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/sys v0.21.0 // indirect
|
||||
golang.org/x/term v0.21.0 // indirect
|
||||
golang.org/x/text v0.16.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/genproto v0.0.0-20240102182953-50ed04b92917 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
|
||||
@ -224,20 +238,23 @@ replace (
|
||||
// Use the cosmos keyring code
|
||||
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.4-kava.1
|
||||
github.com/cometbft/cometbft-db => github.com/kava-labs/cometbft-db v0.9.1-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.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/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
|
||||
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
|
||||
// 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
|
||||
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
|
||||
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
|
||||
)
|
||||
|
244
go.sum
244
go.sum
@ -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.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU=
|
||||
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.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU=
|
||||
cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM=
|
||||
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.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY=
|
||||
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.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.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk=
|
||||
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
|
||||
cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg=
|
||||
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/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
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/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 v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI=
|
||||
cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8=
|
||||
cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc=
|
||||
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.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI=
|
||||
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.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.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w=
|
||||
cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8=
|
||||
cloud.google.com/go/storage v1.36.0 h1:P0mOkAcaJxhCTvAkMhxMfrTKiNcub4YmmPBtlhAyTr8=
|
||||
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.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g=
|
||||
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=
|
||||
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=
|
||||
github.com/0glabs/cosmos-sdk v0.47.10-0glabs.3 h1:Wx3tVMTuFaaHDeJT/OzT7QLfAIpeaZsG9R6XoTOyKCw=
|
||||
github.com/0glabs/cosmos-sdk v0.47.10-0glabs.3/go.mod h1:BWo24B8cApWcO2/widWYIdt3CPxbh+HCSypCPpjTjog=
|
||||
github.com/0glabs/ethermint v0.21.0-0g.v3.0.3 h1:QNrXBQV5L/9FvYRUzJRXMV745xBmJhIP0aEdo0u8x+8=
|
||||
github.com/0glabs/ethermint v0.21.0-0g.v3.0.3/go.mod h1:HYQUhvcZBIG71H3xlxQSk0XyQEjeaHsduOj6O2QImrE=
|
||||
github.com/0glabs/cosmos-sdk v0.47.10-0glabs.5 h1:CwL3i7ccMjOXpKnJ9w0WkM7UpTWLXa/W2ZAwpxFUfb8=
|
||||
github.com/0glabs/cosmos-sdk v0.47.10-0glabs.5/go.mod h1:KskIVnhXTFqrw7CDccMvx7To5KzUsOomIsQV7sPGOog=
|
||||
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.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/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4=
|
||||
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/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.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/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
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/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
|
||||
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.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.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
|
||||
github.com/btcsuite/btcd v0.23.4 h1:IzV6qqkfwbItOS/sg/aDfPDsjPP8twrCOE2R93hxMlQ=
|
||||
github.com/btcsuite/btcd v0.23.4/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.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo=
|
||||
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.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
|
||||
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/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.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ=
|
||||
github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0=
|
||||
github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8=
|
||||
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.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.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/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=
|
||||
@ -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/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
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.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
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/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
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-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-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/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw=
|
||||
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/errors v1.10.0/go.mod h1:lknhIsEVQ9Ss/qKDBQS/UqFSvPQjOwNq2qyKAxtHRqE=
|
||||
github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4=
|
||||
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/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/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/coinbase/kryptology v1.8.0/go.mod h1:RYXOAPdzOGUe3qlSFkMGn58i3xUA8hmxYHksuq+8ciI=
|
||||
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/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk=
|
||||
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-proto v1.0.0-beta.4/go.mod h1:oeB+FyVzG3XrQJbJng0EnV8Vljfk9XvTIpGILNU/9Co=
|
||||
github.com/cosmos/cosmos-db v1.0.2 h1:hwMjozuY1OlJs/uh6vddqnk9j7VamLv+0DBlbEXbAKs=
|
||||
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 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
|
||||
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.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoKuI=
|
||||
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/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=
|
||||
@ -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/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo=
|
||||
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.1/go.mod h1:5tv2RVJEd2+Y38TIQN4CRjJeQGyqOEiKJDfqhk5UjqE=
|
||||
github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM=
|
||||
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/go.mod h1:SImAZkb96YbwvoRkzSMQB6noNJXFgWl/ENIznEoYQI4=
|
||||
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/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.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/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM=
|
||||
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/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/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.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.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4=
|
||||
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 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
|
||||
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/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M=
|
||||
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/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
|
||||
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.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=
|
||||
@ -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.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 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/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
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.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o=
|
||||
github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
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/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
|
||||
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/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/getsentry/sentry-go v0.23.0 h1:dn+QRCeJv4pPt9OjVXiMcGIBIefaTJPw/h0bZWO05nE=
|
||||
github.com/getsentry/sentry-go v0.23.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
||||
github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
|
||||
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/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=
|
||||
@ -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.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.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4=
|
||||
github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs=
|
||||
github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU=
|
||||
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/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||
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/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.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
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/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
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/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 v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
|
||||
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
|
||||
github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
|
||||
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-20190702054246-869f871628b6/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.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||
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.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
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.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
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.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.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
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.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
||||
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.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
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.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744=
|
||||
github.com/hashicorp/go-getter v1.7.5 h1:dT58k9hQ/vbxNMwoI5+xFYAJuv6152UNvdHokfI5wE4=
|
||||
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.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
|
||||
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/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.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 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/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
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/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/kava-labs/cometbft v0.37.4-kava.1 h1:QRuyBieWdUBpe4pcXgzu1SdMH2lkTaqXr/JPIeqdiHE=
|
||||
github.com/kava-labs/cometbft v0.37.4-kava.1/go.mod h1:Cmg5Hp4sNpapm7j+x0xRyt2g0juQfmB752ous+pA0G8=
|
||||
github.com/kava-labs/cometbft-db v0.9.1-kava.1 h1:0KmSPdXYdRp6TsgKuMxRnMZCMEGC5ysIVjuJddYr4tw=
|
||||
github.com/kava-labs/cometbft-db v0.9.1-kava.1/go.mod h1:iliyWaoV0mRwBJoizElCwwRA9Tf7jZJOURcRZF9m60U=
|
||||
github.com/kava-labs/cometbft v0.37.9-kava.1 h1:0mMsAhpV8p0peD9sabIZ//M4nP6LiiZ0o34gfuHdANY=
|
||||
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.2 h1:ZQaio886ifvml9XtJB4IYHhlArgA3+/a5Zwidg7H2J8=
|
||||
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.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
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.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
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.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
||||
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/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
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.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
||||
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-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.6/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY=
|
||||
github.com/linxGnu/grocksdb v1.8.13 h1:X3Id7Obhf8qLY9WPc4LmmtIyabmdDf810XSFDnLlW7E=
|
||||
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/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
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.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
|
||||
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/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=
|
||||
@ -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.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-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU=
|
||||
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
|
||||
github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67 h1:jik8PHtAIsPlCRJjJzl4udgEf7hawInF9texMeO2jrU=
|
||||
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/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=
|
||||
@ -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.1.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.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
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.2.0/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.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.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
|
||||
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
|
||||
github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
|
||||
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/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
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.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.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
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.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo=
|
||||
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/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
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/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=
|
||||
@ -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/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
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 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
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/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
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.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
||||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
||||
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.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.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/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
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.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg=
|
||||
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
|
||||
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.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA=
|
||||
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.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.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.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.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
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.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.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
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/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
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/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/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg=
|
||||
github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
|
||||
github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI=
|
||||
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.14.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
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.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
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/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
|
||||
go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
|
||||
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
|
||||
go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
|
||||
go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
|
||||
go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
|
||||
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw=
|
||||
go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y=
|
||||
go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI=
|
||||
go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg=
|
||||
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.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.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/go.mod h1:J0y0rp9L3xiff1+ZBfKxlC1fz2+aO16tw0tsDOixfuM=
|
||||
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.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/zap v1.9.1/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.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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
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-20190226205417-e64efc72b421/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-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.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
|
||||
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
|
||||
golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
|
||||
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-20181108010431-42b317875d0f/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.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.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4=
|
||||
google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY=
|
||||
google.golang.org/api v0.162.0 h1:Vhs54HkaEpkMBdgGdOT2P6F0csGG/vxDS0hWHJzmmps=
|
||||
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.2.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-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-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg=
|
||||
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917/go.mod h1:pZqR+glSb11aJ+JQcczCvgf47+duRuzNSKqE8YAQnV0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 h1:s1w3X6gQxwrLEpxnLd/qXTVLgQE2yXwaOaoa6IlY/+o=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0/go.mod h1:CAny0tYF+0/9rmDB9fahA9YLzX3+AEVl1qXbv5hhj6c=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 h1:gphdwh0npgs8elJ4T6J+DQJHPVF7RsuJHCfwztUb4J4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA=
|
||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY=
|
||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0=
|
||||
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-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4=
|
||||
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.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
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.50.0/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.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
|
||||
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
|
||||
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/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=
|
||||
@ -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.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.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
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/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=
|
||||
|
52
golangci.yml
52
golangci.yml
@ -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
|
42
proto/zgc/precisebank/v1/genesis.proto
Normal file
42
proto/zgc/precisebank/v1/genesis.proto
Normal 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
|
||||
];
|
||||
}
|
62
proto/zgc/precisebank/v1/query.proto
Normal file
62
proto/zgc/precisebank/v1/query.proto
Normal 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];
|
||||
}
|
52
tests/e2e-ibc/chainconfig.go
Normal file
52
tests/e2e-ibc/chainconfig.go
Normal 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},
|
||||
}
|
||||
}
|
59
tests/e2e-ibc/conformance_test.go
Normal file
59
tests/e2e-ibc/conformance_test.go
Normal 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
290
tests/e2e-ibc/erc20_test.go
Normal 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(), ¶mChange)
|
||||
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
297
tests/e2e-ibc/go.mod
Normal 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
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
206
tests/e2e-ibc/main_test.go
Normal 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())
|
||||
})
|
||||
}
|
@ -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=true
|
||||
# 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.
|
||||
# If IBC tests are enabled this should be >30. Otherwise, this should be >10.
|
||||
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=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:
|
||||
# - the E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC has nonzero balance
|
||||
|
@ -1,127 +1,102 @@
|
||||
package e2e_test
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
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"
|
||||
precisebanktypes "github.com/0glabs/0g-chain/x/precisebank/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
)
|
||||
|
||||
func (suite *IntegrationTestSuite) TestUpgradeParams_SDK() {
|
||||
func (suite *IntegrationTestSuite) TestUpgrade_PreciseBankReserveTransfer() {
|
||||
suite.SkipIfUpgradeDisabled()
|
||||
|
||||
beforeUpgradeCtx := suite.ZgChain.Grpc.CtxAtHeight(suite.UpgradeHeight - 1)
|
||||
afterUpgradeCtx := suite.ZgChain.Grpc.CtxAtHeight(suite.UpgradeHeight)
|
||||
|
||||
// Before params
|
||||
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
|
||||
suite.Run("x/gov parameters before upgrade", func() {
|
||||
suite.Assert().Nil(
|
||||
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() {
|
||||
suite.Assert().Equal(
|
||||
mustParseDuration("172800s"),
|
||||
govParamsAfter.DepositParams.MaxDepositPeriod,
|
||||
"x/gov DepositParams max deposit period after upgrade should be 172800s",
|
||||
)
|
||||
suite.Assert().Equal(
|
||||
[]sdk.Coin{{Denom: "ua0gi", Amount: sdk.NewInt(10_000_000)}},
|
||||
govParamsAfter.DepositParams.MinDeposit,
|
||||
"x/gov DepositParams min deposit after upgrade should be 10_000_000 ukava",
|
||||
)
|
||||
|
||||
expectedParams := govtypes.Params{
|
||||
MinDeposit: sdk.NewCoins(sdk.NewCoin("ua0gi", sdk.NewInt(10_000_000))),
|
||||
MaxDepositPeriod: mustParseDuration("172800s"),
|
||||
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")
|
||||
})
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) TestUpgradeParams_Consensus() {
|
||||
suite.SkipIfUpgradeDisabled()
|
||||
|
||||
afterUpgradeCtx := suite.ZgChain.Grpc.CtxAtHeight(suite.UpgradeHeight)
|
||||
|
||||
grpcClient := suite.ZgChain.Grpc
|
||||
paramsAfter, err := grpcClient.Query.Consensus.Params(afterUpgradeCtx, &consensustypes.QueryParamsRequest{})
|
||||
suite.NoError(err)
|
||||
|
||||
// v25 consensus params from x/params should be migrated to x/consensus
|
||||
expectedParams := tmproto.ConsensusParams{
|
||||
Block: &tmproto.BlockParams{
|
||||
MaxBytes: 22020096,
|
||||
MaxGas: 20000000,
|
||||
},
|
||||
Evidence: &tmproto.EvidenceParams{
|
||||
MaxAgeNumBlocks: 100000,
|
||||
MaxAgeDuration: *mustParseDuration("172800s"),
|
||||
MaxBytes: 1048576,
|
||||
},
|
||||
Validator: &tmproto.ValidatorParams{
|
||||
PubKeyTypes: []string{
|
||||
tmtypes.ABCIPubKeyTypeEd25519,
|
||||
},
|
||||
},
|
||||
Version: nil,
|
||||
}
|
||||
suite.Require().Equal(expectedParams, *paramsAfter.Params, "x/consensus params after upgrade should be as expected")
|
||||
}
|
||||
|
||||
// func (suite *IntegrationTestSuite) TestUpgradeParams_CDP_Interval() {
|
||||
// suite.SkipIfUpgradeDisabled()
|
||||
|
||||
// beforeUpgradeCtx := suite.Kava.Grpc.CtxAtHeight(suite.UpgradeHeight - 1)
|
||||
// afterUpgradeCtx := suite.Kava.Grpc.CtxAtHeight(suite.UpgradeHeight)
|
||||
|
||||
// grpcClient := suite.Kava.Grpc
|
||||
|
||||
// paramsBefore, err := grpcClient.Query.Cdp.Params(beforeUpgradeCtx, &cdptypes.QueryParamsRequest{})
|
||||
// suite.Require().NoError(err)
|
||||
// paramsAfter, err := grpcClient.Query.Cdp.Params(afterUpgradeCtx, &cdptypes.QueryParamsRequest{})
|
||||
// suite.Require().NoError(err)
|
||||
// -----------------------------
|
||||
// Get initial reserve balances
|
||||
evmutilAddr := "kava1w9vxuke5dz6hyza2j932qgmxltnfxwl78u920k"
|
||||
precisebankAddr := "kava12yfe2jaupmtjruwxsec7hg7er60fhaa4uz7ffl"
|
||||
|
||||
// expectedParams := paramsBefore.Params
|
||||
// expectedParams.LiquidationBlockInterval = int64(50)
|
||||
previousEvmutilBalRes, err := grpcClient.Query.Bank.Balance(beforeUpgradeCtx, &banktypes.QueryBalanceRequest{
|
||||
Address: evmutilAddr,
|
||||
Denom: precisebanktypes.IntegerCoinDenom,
|
||||
})
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(previousEvmutilBalRes.Balance)
|
||||
suite.Require().True(
|
||||
previousEvmutilBalRes.Balance.Amount.IsPositive(),
|
||||
"should have reserve balance before upgrade",
|
||||
)
|
||||
|
||||
// suite.Require().Equal(expectedParams, paramsAfter.Params,
|
||||
// "expected cdp parameters to equal previous parameters with a liquidation block interval of 100")
|
||||
// }
|
||||
previousPrecisebankBalRes, err := grpcClient.Query.Bank.Balance(beforeUpgradeCtx, &banktypes.QueryBalanceRequest{
|
||||
Address: precisebankAddr,
|
||||
Denom: precisebanktypes.IntegerCoinDenom,
|
||||
})
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(previousPrecisebankBalRes.Balance)
|
||||
suite.Require().True(
|
||||
previousPrecisebankBalRes.Balance.Amount.IsZero(),
|
||||
"should be empty before upgrade",
|
||||
)
|
||||
|
||||
func mustParseDuration(s string) *time.Duration {
|
||||
d, err := time.ParseDuration(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return &d
|
||||
suite.T().Logf("x/evmutil balances before upgrade: %s", previousEvmutilBalRes.Balance)
|
||||
suite.T().Logf("x/precisebank balances before upgrade: %s", previousPrecisebankBalRes.Balance)
|
||||
|
||||
// -----------------------------
|
||||
// After upgrade
|
||||
// - Check reserve balance transfer
|
||||
// - Check reserve fully backs fractional amounts
|
||||
afterEvmutilBalRes, err := grpcClient.Query.Bank.Balance(afterUpgradeCtx, &banktypes.QueryBalanceRequest{
|
||||
Address: evmutilAddr,
|
||||
Denom: precisebanktypes.IntegerCoinDenom,
|
||||
})
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(afterEvmutilBalRes.Balance)
|
||||
suite.Require().Truef(
|
||||
afterEvmutilBalRes.Balance.Amount.IsZero(),
|
||||
"should have transferred all reserve balance to precisebank, expected 0 but got %s",
|
||||
afterEvmutilBalRes.Balance,
|
||||
)
|
||||
|
||||
afterPrecisebankBalRes, err := grpcClient.Query.Bank.Balance(afterUpgradeCtx, &banktypes.QueryBalanceRequest{
|
||||
Address: precisebankAddr,
|
||||
Denom: precisebanktypes.IntegerCoinDenom,
|
||||
})
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(afterPrecisebankBalRes.Balance)
|
||||
// 2 total in reserve- genesis.json has 5 accounts with fractional balances
|
||||
// totalling 2 integer coins
|
||||
suite.Require().Equal(int64(2), afterPrecisebankBalRes.Balance.Amount.Int64())
|
||||
|
||||
suite.T().Logf("x/evmutil balances after upgrade: %s", afterEvmutilBalRes.Balance)
|
||||
suite.T().Logf("x/precisebank balances after upgrade: %s", afterPrecisebankBalRes.Balance)
|
||||
|
||||
sumFractional, err := grpcClient.Query.Precisebank.TotalFractionalBalances(
|
||||
afterUpgradeCtx,
|
||||
&precisebanktypes.QueryTotalFractionalBalancesRequest{},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Require().Equal(
|
||||
sumFractional.Total.Amount,
|
||||
afterPrecisebankBalRes.Balance.Amount.Mul(precisebanktypes.ConversionFactor()),
|
||||
"reserve should match exactly sum fractional balances",
|
||||
)
|
||||
|
||||
// Check remainder + total fractional balances = reserve balance
|
||||
remainderRes, err := grpcClient.Query.Precisebank.Remainder(
|
||||
afterUpgradeCtx,
|
||||
&precisebanktypes.QueryRemainderRequest{},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
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
|
@ -13,11 +13,9 @@ import (
|
||||
|
||||
sdkmath "cosmossdk.io/math"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/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/common"
|
||||
@ -208,17 +206,15 @@ func (a *SigningAccount) SignAndBroadcastEvmTx(req util.EvmTxRequest) EvmTxRespo
|
||||
|
||||
// SignRawEvmData signs raw evm data with the SigningAccount's private key.
|
||||
// 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)
|
||||
return keyringSigner.SignByAddress(a.SdkAddress, msg)
|
||||
}
|
||||
|
||||
// NewFundedAccount creates a SigningAccount for a random account & funds the account from the whale.
|
||||
func (chain *Chain) NewFundedAccount(name string, funds sdk.Coins) *SigningAccount {
|
||||
entropy, err := bip39.NewEntropy(128)
|
||||
require.NoErrorf(chain.t, err, "failed to generate entropy for account %s: %s", name, err)
|
||||
mnemonic, err := bip39.NewMnemonic(entropy)
|
||||
require.NoErrorf(chain.t, err, "failed to create new mnemonic for account %s: %s", name, err)
|
||||
mnemonic, err := util.RandomMnemonic()
|
||||
require.NoError(chain.t, err)
|
||||
|
||||
acc := chain.AddNewSigningAccount(
|
||||
name,
|
||||
|
@ -217,7 +217,7 @@ func (suite *E2eTestSuite) SkipIfIbcDisabled() {
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (suite *E2eTestSuite) SkipIfUpgradeDisabled() {
|
||||
if suite.config.Kvtool != nil && !suite.config.Kvtool.IncludeAutomatedUpgrade {
|
||||
|
@ -1,7 +1,9 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/go-bip39"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
@ -12,3 +14,12 @@ func SdkToEvmAddress(addr sdk.AccAddress) common.Address {
|
||||
func EvmToSdkAddress(addr common.Address) sdk.AccAddress {
|
||||
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)
|
||||
}
|
||||
|
@ -3,17 +3,21 @@ package util
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -77,6 +81,21 @@ func NewEvmSigner(
|
||||
}, 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 := ðsecp256k1.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 {
|
||||
responses := make(chan EvmTxResponse)
|
||||
|
||||
|
@ -358,7 +358,7 @@ func (s *ZgChainSigner) Run(requests <-chan ZgChainMsgRequest) (<-chan ZgChainMs
|
||||
currentRequest = nil
|
||||
}
|
||||
|
||||
// immediatley response to channel
|
||||
// immediately response to channel
|
||||
responses <- *response
|
||||
// go to next request
|
||||
broadcastTxSeq++
|
||||
|
15
third_party/proto/cosmos_proto/cosmos.proto
vendored
15
third_party/proto/cosmos_proto/cosmos.proto
vendored
@ -5,6 +5,12 @@ import "google/protobuf/descriptor.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 {
|
||||
|
||||
// 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
|
||||
// file option.
|
||||
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 {
|
||||
@ -27,6 +36,9 @@ extend google.protobuf.FieldOptions {
|
||||
// generators may choose to use this information to map this field to a
|
||||
// language-specific type representing the scalar.
|
||||
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 {
|
||||
@ -46,6 +58,9 @@ extend google.protobuf.FileOptions {
|
||||
// expected that the declaration will be found in a protobuf file named
|
||||
// a/b/scalars.proto in the file descriptor set.
|
||||
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
|
||||
|
19
third_party/proto/ethermint/evm/v1/evm.proto
vendored
19
third_party/proto/ethermint/evm/v1/evm.proto
vendored
@ -18,12 +18,17 @@ message Params {
|
||||
repeated int64 extra_eips = 4 [(gogoproto.customname) = "ExtraEIPs", (gogoproto.moretags) = "yaml:\"extra_eips\""];
|
||||
// chain_config defines the EVM chain configuration parameters
|
||||
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
|
||||
[(gogoproto.customname) = "EIP712AllowedMsgs", (gogoproto.nullable) = false];
|
||||
// allow_unprotected_txs defines if replay-protected (i.e non EIP155
|
||||
// signed) transactions can be executed on the state machine.
|
||||
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
|
||||
@ -246,20 +251,20 @@ message TraceConfig {
|
||||
|
||||
// EIP712AllowedMsg stores an allowed legacy msg and its eip712 type.
|
||||
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;
|
||||
|
||||
// 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;
|
||||
|
||||
// types of the msg value
|
||||
// value_types is a list of msg value types
|
||||
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];
|
||||
}
|
||||
|
||||
// EIP712MsgType is the eip712 type of a single message.
|
||||
// EIP712NestedMsgType is the eip712 type of a single message.
|
||||
message EIP712NestedMsgType {
|
||||
// name of the nested type. ie "Fee", "Coin"
|
||||
string name = 1;
|
||||
@ -270,6 +275,8 @@ message EIP712NestedMsgType {
|
||||
|
||||
// EIP712MsgAttrType is the eip712 type of a single message attribute.
|
||||
message EIP712MsgAttrType {
|
||||
// name
|
||||
string name = 1;
|
||||
// type
|
||||
string type = 2;
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ func (suite *ABCITestSuite) TestBeginBlocker_UpdateExpiredAtomicSwaps() {
|
||||
// Run the second begin blocker
|
||||
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 {
|
||||
storedSwap, found := suite.keeper.GetAtomicSwap(tc.secondCtx, swapID)
|
||||
if tc.expectInStorage {
|
||||
|
@ -431,7 +431,7 @@ func (suite *AssetTestSuite) TestIncrementOutgoingAssetSupply() {
|
||||
true,
|
||||
},
|
||||
{
|
||||
"outoing + amount > current",
|
||||
"outgoing + amount > current",
|
||||
args{
|
||||
coin: c("bnb", 36),
|
||||
},
|
||||
|
@ -67,7 +67,7 @@ func (a AtomicSwap) Validate() error {
|
||||
if a.Recipient.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) == "" {
|
||||
return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender other chain cannot be blank")
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ func (k Keeper) GetTokenCommitteeProposalResult(ctx sdk.Context, proposalID uint
|
||||
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
|
||||
// required for proposal to pass), and quorum (votes tallied at this percentage).
|
||||
func (k Keeper) TallyTokenCommitteeVotes(ctx sdk.Context, proposalID uint64,
|
||||
|
@ -381,7 +381,7 @@ func MustNewProposal(pubProposal PubProposal, id uint64, committeeID uint64, dea
|
||||
return proposal
|
||||
}
|
||||
|
||||
// GetPubProposal returns the PubProposal (govtypes.Content)
|
||||
// GetContent returns the PubProposal (govtypes.Content)
|
||||
func (p Proposal) GetContent() PubProposal {
|
||||
content, ok := p.Content.GetCachedValue().(PubProposal)
|
||||
if !ok {
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
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
|
||||
|
||||
// NewGenesisState returns a new genesis state object for the module.
|
||||
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -6,14 +6,11 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
"github.com/0glabs/0g-chain/chaincfg"
|
||||
"github.com/0glabs/0g-chain/x/evmutil/types"
|
||||
)
|
||||
|
||||
// RegisterInvariants registers the swap module invariants
|
||||
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))
|
||||
// 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))
|
||||
@ -22,57 +19,11 @@ func RegisterInvariants(ir sdk.InvariantRegistry, bankK types.BankKeeper, k Keep
|
||||
// AllInvariants runs all invariants of the swap module
|
||||
func AllInvariants(bankK types.BankKeeper, k Keeper) sdk.Invariant {
|
||||
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 {
|
||||
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.
|
||||
//
|
||||
// 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
|
||||
return CosmosCoinsFullyBackedInvariant(bankK, k)(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ func (suite *invariantTestSuite) SetupValidState() {
|
||||
for i := 0; i < 4; i++ {
|
||||
suite.Keeper.SetAccount(suite.Ctx, *types.NewAccount(
|
||||
suite.Addrs[i],
|
||||
keeper.ConversionMultiplier.QuoRaw(2),
|
||||
sdkmath.NewInt(10000000000),
|
||||
))
|
||||
}
|
||||
suite.FundModuleAccountWithZgChain(
|
||||
@ -97,7 +97,7 @@ func (suite *invariantTestSuite) SetupValidState() {
|
||||
suite.NoError(err)
|
||||
}
|
||||
|
||||
// RegisterRoutes implements sdk.InvariantRegistry
|
||||
// RegisterRoute implements sdk.InvariantRegistry
|
||||
func (suite *invariantTestSuite) RegisterRoute(moduleName string, route string, invariant sdk.Invariant) {
|
||||
_, exists := suite.invariants[moduleName]
|
||||
|
||||
@ -132,45 +132,6 @@ func (suite *invariantTestSuite) runInvariant(route string, invariant func(bankK
|
||||
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
|
||||
// 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.
|
||||
|
@ -4,34 +4,6 @@ order: 1
|
||||
|
||||
# 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
|
||||
|
||||
`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.
|
||||
|
||||
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.
|
||||
|
||||
@ -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.
|
||||
|
||||
`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.
|
||||
|
@ -51,24 +51,12 @@ message AllowedCosmosCoinERC20Token {
|
||||
|
||||
```protobuf
|
||||
message GenesisState {
|
||||
repeated Account accounts = 1 [(gogoproto.nullable) = false];
|
||||
// previously stored accounts containing fractional balances.
|
||||
reserved 1;
|
||||
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
|
||||
|
||||
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.
|
||||
|
@ -21,13 +21,6 @@ parent:
|
||||
|
||||
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
|
||||
|
||||
evmutil exposes messages to allow for the conversion of Kava ERC20 tokens and sdk.Coins via a whitelist.
|
||||
|
@ -51,7 +51,6 @@ type Suite struct {
|
||||
BankKeeper bankkeeper.Keeper
|
||||
AccountKeeper authkeeper.AccountKeeper
|
||||
Keeper keeper.Keeper
|
||||
EvmBankKeeper keeper.EvmBankKeeper
|
||||
Addrs []sdk.AccAddress
|
||||
EvmModuleAddr sdk.AccAddress
|
||||
QueryClient types.QueryClient
|
||||
@ -69,7 +68,6 @@ func (suite *Suite) SetupTest() {
|
||||
suite.BankKeeper = tApp.GetBankKeeper()
|
||||
suite.AccountKeeper = tApp.GetAccountKeeper()
|
||||
suite.Keeper = tApp.GetEvmutilKeeper()
|
||||
suite.EvmBankKeeper = keeper.NewEvmBankKeeper(tApp.GetEvmutilKeeper(), suite.BankKeeper, suite.AccountKeeper)
|
||||
suite.EvmModuleAddr = suite.AccountKeeper.GetModuleAddress(evmtypes.ModuleName)
|
||||
|
||||
// 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
Loading…
Reference in New Issue
Block a user