From 3e3a0894ac7ecce18ae0c570eb02e9def80a1359 Mon Sep 17 00:00:00 2001 From: alexstratos Date: Mon, 21 Mar 2022 13:17:28 -0400 Subject: [PATCH 01/17] fix query total ozone supply --- x/register/keeper/keeper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/register/keeper/keeper.go b/x/register/keeper/keeper.go index a9f75659..d72c1e4f 100644 --- a/x/register/keeper/keeper.go +++ b/x/register/keeper/keeper.go @@ -575,6 +575,6 @@ func (k Keeper) UozSupply(ctx sdk.Context) (remaining, total sdk.Int) { S := k.GetInitialGenesisStakeTotal(ctx) Pt := k.GetTotalUnissuedPrepay(ctx).Amount // total supply = Lt * ( 1 + Pt / S ) - total = (Pt.ToDec().Quo(S.ToDec()).TruncateInt().Add(sdk.NewInt(1))).Mul(remaining) + total = (Pt.ToDec().Quo(S.ToDec()).Add(sdk.NewDec(1))).Mul(remaining.ToDec()).TruncateInt() return remaining, total } From 6c28e866ed1060a4d7c4a8257381ecb897b09f20 Mon Sep 17 00:00:00 2001 From: hong-pang <82901282+hong-pang@users.noreply.github.com> Date: Fri, 22 Jul 2022 12:17:47 -0400 Subject: [PATCH 02/17] doc/update README.md update README.md for tropos-4 --- README.md | 90 ++++++++++++------------------------------------------- 1 file changed, 19 insertions(+), 71 deletions(-) diff --git a/README.md b/README.md index 77d20d85..7c2992ae 100644 --- a/README.md +++ b/README.md @@ -25,80 +25,21 @@ - Platform - * Linux(tested on Ubuntu18.04 and 20.04) - * Mac OS - * Windows + * Linux(tested on Ubuntu18.04 and 20.04) + * Mac OS + * Windows - It is possible to build and run the software on Windows. However, we did not test it on Windows completely. - It may give you unexpected results, or it may require additional setup. + It is possible to build and run the software on Windows. However, we did not test it on Windows completely. + It may give you unexpected results, or it may require additional setup. - An alternative option is to install a separate virtual Linux system using [VirtualBox](https://www.virtualbox.org/wiki/Downloads) or [VMware Workstation](https://www.vmware.com/ca/products/workstation-player/workstation-player-evaluation.html) - ---- --- - -## Executables - -The `Stratos-Chain` comes with 2 types of executables that can be found in `stratos/stratos-chain/build` directory. - -| Command | Description | -| :-----------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `stchaincli` | the client end. It is the command line interface for interacting with `stchaind`. It is the entry point into the Stratos network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Stratos network via JSON RPC endpoints. | -| `stchaind` | the app Daemon (server)| - - -### `stchaincli` - -``` -Usage: - stchaincli [command] - -Available Commands: - status Query remote node for status - config Create or query an application CLI configuration file - query Querying subcommands - tx Transactions subcommands - rest-server Start LCD (light-client daemon), a local REST server - keys Add or view local private keys - version Print the app version - help Help about any command -``` - -Each `stchaincli` command may contain a set of flags or parameters. for more details, please refer to [Stratos Chain `stchaincli` Commands(Part1)](https://github.com/stratosnet/stratos-chain/wiki/Stratos-Chain-%60stchaincli%60-Commands(Part1)) and [Stratos Chain `stchaincli` Commands(Part2)](https://github.com/stratosnet/stratos-chain/wiki/Stratos-Chain-%60stchaincli%60-Commands(Part2)) - -### `stchaind` - -``` -Usage: - stchaind [command] - -Available Commands: - init Initialize private validator, p2p, genesis, and application configuration files - collect-gentxs Collect genesis txs and output a genesis.json file - migrate Migrate genesis to a specified target version - gentx Generate a genesis tx carrying a self delegation - validate-genesis validates the genesis file at the default location or at the location passed as an arg - add-genesis-account Add a genesis account to genesis.json - faucet Run a faucet cmd - debug Tool for helping with debugging your application - start Run the full node - unsafe-reset-all Resets the blockchain database, removes address book files, and resets priv_validator.json to the genesis state - tendermint Tendermint subcommands - export Export state to JSON - version Print the app version - help Help about any command -``` - -Each `stchaind` command may contain a set of flags or parameters. for more details, please refer to [Stratos-chain `stchaind` Commands](https://github.com/stratosnet/stratos-chain/wiki/Stratos-Chain-%60stchaind%60-Commands) + An alternative option is to install a separate virtual Linux system using [VirtualBox](https://www.virtualbox.org/wiki/Downloads) or [VMware Workstation](https://www.vmware.com/ca/products/workstation-player/workstation-player-evaluation.html) --- --- ## Connect to `Stratos` Network -Going through all the possible command line flags is out of scope here, -but we've enumerated a few common parameter combos to get you up to speed quickly on how you can run your own `Stratos` instance. - ### A Full node on the test Stratos network -For prerequisites and detailed instructions of connecting to `Tropos Incentive Testnet` network, please read the [Tropos Incentive Testnet](https://github.com/stratosnet/sds/wiki/Tropos-Incentive-Testnet). +For prerequisites and detailed instructions of connecting to `Tropos Incentive Testnet` network, please refer to [Connecting to Tropos Incentive Testnet](https://github.com/stratosnet/sds/wiki/Tropos-Incentive-Testnet). ### Full node on the main Stratos network - TBA Prerequisites and detailed instructions of main network will be added later. @@ -113,17 +54,24 @@ Prerequisites and detailed instructions of main network will be added later. ## References -* [`stchaincli` Commands(Part1)](https://github.com/stratosnet/stratos-chain/wiki/Stratos-Chain-%60stchaincli%60-Commands(Part1)) +
+ Stratos-chain document List + +
+ +* [Tropos Incentive Testnet](https://github.com/stratosnet/sds/wiki/Tropos-Incentive-Testnet) + +* ['stchaind' Commands(part1)](https://github.com/stratosnet/stratos-chain/wiki/Stratos-Chain-%60stchaind%60-Commands(part1)) -* [`stchaincli` Commands(Part2)](https://github.com/stratosnet/stratos-chain/wiki/Stratos-Chain-%60stchaincli%60-Commands(Part2)) +* [stchaind' Commands(part2)](https://github.com/stratosnet/stratos-chain/wiki/Stratos-Chain-%60stchaind%60-Commands(part2)) -* [`stchaind` Commands](https://github.com/stratosnet/stratos-chain/wiki/Stratos-Chain-%60stchaind%60-Commands) +* [gRPC Queries](https://github.com/stratosnet/stratos-chain/wiki/Stratos-Chain-gRPC-Queries) * [REST APIs](https://github.com/stratosnet/stratos-chain/wiki/Stratos-Chain-REST-APIs) * [How to become a validator](https://github.com/stratosnet/stratos-chain/wiki/How-to-Become-a-Validator) -* [`ppd terminal` subcommands](https://github.com/stratosnet/sds/wiki/%60ppd-terminal%60--subcommands) +
--- --- @@ -143,7 +91,7 @@ Please make sure your contributions adhere to our coding guidelines: guidelines. * Pull requests need to be based on and opened against the `main` branch. * Commit messages should be prefixed with the package(s) they modify. - * E.g. "eth, rpc: make trace configs optional" + * E.g. "eth, rpc: make trace configs optional" --- --- From 16ca882f26534aa112434139d050c8f5a032e3c8 Mon Sep 17 00:00:00 2001 From: weichen-qsnetwork Date: Mon, 16 Jan 2023 09:26:02 -0500 Subject: [PATCH 03/17] QB-1532 Add Dockerfile for integration test --- Makefile | 6 ++++++ tests/e2e/Dockerfile | 39 +++++++++++++++++++++++++++++++++++++++ tests/e2e/entrypoint.sh | 3 +++ 3 files changed, 48 insertions(+) create mode 100644 tests/e2e/Dockerfile create mode 100644 tests/e2e/entrypoint.sh diff --git a/Makefile b/Makefile index 6497e710..f1a60bc8 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ BUILDDIR ?= $(CURDIR)/build APP_VER := v0.8.0 COMMIT := $(GIT_COMMIT_HASH) +TEST_DOCKER_REPO=stratos-chain-e2e ifeq ($(COMMIT),) VERSION := $(APP_VER) @@ -54,4 +55,9 @@ localnet-start: build-linux localnet-stop localnet-stop: docker-compose down +build-docker-e2e: + @docker build -f tests/e2e/Dockerfile -t ${TEST_DOCKER_REPO}:$(shell git rev-parse --short HEAD) . + @docker tag ${TEST_DOCKER_REPO}:$(shell git rev-parse --short HEAD) ${TEST_DOCKER_REPO}:$(shell git rev-parse --abbrev-ref HEAD | sed 's#/#_#g') + @docker tag ${TEST_DOCKER_REPO}:$(shell git rev-parse --short HEAD) ${TEST_DOCKER_REPO}:latest + .PHONY: build-linux build-mac build clean diff --git a/tests/e2e/Dockerfile b/tests/e2e/Dockerfile new file mode 100644 index 00000000..1f2fb6a0 --- /dev/null +++ b/tests/e2e/Dockerfile @@ -0,0 +1,39 @@ +# Simple usage with a mounted data directory: +# > docker build -t stratos-chain-e2e -f tests/e2e/Dockerfile . +FROM golang:1.19-alpine AS build-env + +# Set up dependencies +ENV PACKAGES curl make git libc-dev bash gcc linux-headers eudev-dev python3 + +# Install minimum necessary dependencies +RUN apk add --no-cache $PACKAGES + +# Set working directory for the build +WORKDIR /go/src/github.com/stratosnet/stratos-chain + +# Add source files +COPY . . +RUN make install + + +# Final image +FROM alpine:edge + +ENV WORK_DIR /stchaind +ENV RUN_AS_USER stratos + +# Install ca-certificates +RUN apk add --update ca-certificates + +RUN addgroup --gid 2048 "$RUN_AS_USER" && \ + adduser -S -G "$RUN_AS_USER" --uid 2048 "$RUN_AS_USER" -h "$WORK_DIR" + +WORKDIR $WORK_DIR + +# Copy over binaries from the build-env +COPY --from=build-env /go/bin/stchaind /usr/bin/stchaind + +COPY tests/e2e/entrypoint.sh /usr/bin/entrypoint.sh +RUN chmod +x /usr/bin/entrypoint.sh +ENTRYPOINT ["/usr/bin/entrypoint.sh"] +CMD ["stchaind"] diff --git a/tests/e2e/entrypoint.sh b/tests/e2e/entrypoint.sh new file mode 100644 index 00000000..8798ab1b --- /dev/null +++ b/tests/e2e/entrypoint.sh @@ -0,0 +1,3 @@ +#!/bin/sh +chown -R $RUN_AS_USER $WORK_DIR +su -s /bin/sh - $RUN_AS_USER -c "$@" From 74f7ba4fcff8c8f85e4f7cba854422e6b08994b0 Mon Sep 17 00:00:00 2001 From: hong-pang <82901282+hong-pang@users.noreply.github.com> Date: Tue, 17 Jan 2023 13:16:29 -0500 Subject: [PATCH 04/17] Update README.md --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7c2992ae..7bb1a9f6 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ - Software(tested version) * Ubuntu 18.04+ - * Go 1.16+ linux/amd64 + * Go 1.18+ linux/amd64 - Platform @@ -39,7 +39,7 @@ ## Connect to `Stratos` Network ### A Full node on the test Stratos network -For prerequisites and detailed instructions of connecting to `Tropos Incentive Testnet` network, please refer to [Connecting to Tropos Incentive Testnet](https://github.com/stratosnet/sds/wiki/Tropos-Incentive-Testnet). +For prerequisites and detailed instructions of connecting to `Tropos Incentive Testnet` network, please refer to [Tropos Incentive Testnet](https://github.com/stratosnet/sds/wiki/Tropos-Incentive-Testnet). ### Full node on the main Stratos network - TBA Prerequisites and detailed instructions of main network will be added later. @@ -60,7 +60,7 @@ Prerequisites and detailed instructions of main network will be added later.
* [Tropos Incentive Testnet](https://github.com/stratosnet/sds/wiki/Tropos-Incentive-Testnet) - + * ['stchaind' Commands(part1)](https://github.com/stratosnet/stratos-chain/wiki/Stratos-Chain-%60stchaind%60-Commands(part1)) * [stchaind' Commands(part2)](https://github.com/stratosnet/stratos-chain/wiki/Stratos-Chain-%60stchaind%60-Commands(part2)) @@ -71,6 +71,8 @@ Prerequisites and detailed instructions of main network will be added later. * [How to become a validator](https://github.com/stratosnet/stratos-chain/wiki/How-to-Become-a-Validator) +* [`ppd terminal` subcommand](https://github.com/stratosnet/sds/wiki/%60ppd-terminal%60--subcommands) + --- --- @@ -91,13 +93,13 @@ Please make sure your contributions adhere to our coding guidelines: guidelines. * Pull requests need to be based on and opened against the `main` branch. * Commit messages should be prefixed with the package(s) they modify. - * E.g. "eth, rpc: make trace configs optional" + * E.g. "eth, rpc: make trace configs optional" --- --- ## License -Copyright 2022 Stratos +Copyright 2023 Stratos Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From a0bf29afd7e4dabc3616ffa0d45aa7822d877d13 Mon Sep 17 00:00:00 2001 From: weichen-qsnetwork Date: Wed, 18 Jan 2023 09:11:31 -0500 Subject: [PATCH 05/17] add uid and gid args --- Makefile | 2 +- tests/e2e/Dockerfile | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index f1a60bc8..2e6c83df 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ localnet-stop: docker-compose down build-docker-e2e: - @docker build -f tests/e2e/Dockerfile -t ${TEST_DOCKER_REPO}:$(shell git rev-parse --short HEAD) . + @docker build -f tests/e2e/Dockerfile -t ${TEST_DOCKER_REPO}:$(shell git rev-parse --short HEAD) --build-arg uid=$(shell id -u) --build-arg gid=$(shell id -g) . @docker tag ${TEST_DOCKER_REPO}:$(shell git rev-parse --short HEAD) ${TEST_DOCKER_REPO}:$(shell git rev-parse --abbrev-ref HEAD | sed 's#/#_#g') @docker tag ${TEST_DOCKER_REPO}:$(shell git rev-parse --short HEAD) ${TEST_DOCKER_REPO}:latest diff --git a/tests/e2e/Dockerfile b/tests/e2e/Dockerfile index 1f2fb6a0..92a8ce91 100644 --- a/tests/e2e/Dockerfile +++ b/tests/e2e/Dockerfile @@ -1,5 +1,5 @@ # Simple usage with a mounted data directory: -# > docker build -t stratos-chain-e2e -f tests/e2e/Dockerfile . +# > docker build -t stratos-chain-e2e --build-arg uid=$(id -u) --build-arg gid=$(id -g) -f tests/e2e/Dockerfile . FROM golang:1.19-alpine AS build-env # Set up dependencies @@ -25,8 +25,11 @@ ENV RUN_AS_USER stratos # Install ca-certificates RUN apk add --update ca-certificates -RUN addgroup --gid 2048 "$RUN_AS_USER" && \ - adduser -S -G "$RUN_AS_USER" --uid 2048 "$RUN_AS_USER" -h "$WORK_DIR" +ARG uid=2048 +ARG gid=2048 + +RUN addgroup --gid $gid "$RUN_AS_USER" && \ + adduser -S -G "$RUN_AS_USER" --uid $uid "$RUN_AS_USER" -h "$WORK_DIR" WORKDIR $WORK_DIR From bf66b06fe4419dd6d7484e428e5fa8e1c151b0e1 Mon Sep 17 00:00:00 2001 From: Xiong Date: Thu, 19 Jan 2023 16:20:13 -0500 Subject: [PATCH 06/17] Optimize queries --- client/utils.go | 23 +++++++++ x/pot/client/rest/query.go | 21 ++++----- x/pot/keeper/querier.go | 95 ++++++++++++++++++-------------------- x/pot/types/querier.go | 44 +++--------------- 4 files changed, 84 insertions(+), 99 deletions(-) create mode 100644 client/utils.go diff --git a/client/utils.go b/client/utils.go new file mode 100644 index 00000000..97fd632c --- /dev/null +++ b/client/utils.go @@ -0,0 +1,23 @@ +package client + +// Paginate result may be out of data range, need to check in the iterator +func Paginate(page, limit, defLimit int) (start, end int) { + if page <= 0 { + // invalid start page + return -1, -1 + } + + // fallback to default limit if supplied limit is invalid + if limit <= 0 { + if defLimit < 0 { + // invalid default limit + return -1, -1 + } + limit = defLimit + } + + start = (page - 1) * limit + end = limit + start + + return start, end +} diff --git a/x/pot/client/rest/query.go b/x/pot/client/rest/query.go index 624434f0..7cfe3e7c 100644 --- a/x/pot/client/rest/query.go +++ b/x/pot/client/rest/query.go @@ -15,9 +15,9 @@ import ( func registerQueryRoutes(clientCtx client.Context, r *mux.Router) { r.HandleFunc("/pot/report/epoch/{epoch}", getVolumeReportHandlerFn(clientCtx, keeper.QueryVolumeReport)).Methods("GET") - r.HandleFunc("/pot/rewards/epoch/{epoch}", getPotRewardsByEpochHandlerFn(clientCtx, keeper.QueryPotRewardsByReportEpoch)).Methods("GET") - r.HandleFunc("/pot/rewards/wallet/{walletAddress}", getPotRewardsByWalletAddrHandlerFn(clientCtx, keeper.QueryPotRewardsByWalletAddr)).Methods("GET") - r.HandleFunc("/pot/slashing/{walletAddress}", getPotSlashingByWalletAddressHandlerFn(clientCtx, keeper.QueryPotSlashingByWalletAddr)).Methods("GET") + r.HandleFunc("/pot/rewards/epoch/{epoch}", getIndividualRewardsByEpochHandlerFn(clientCtx, keeper.QueryIndividualRewardsByReportEpoch)).Methods("GET") + r.HandleFunc("/pot/rewards/wallet/{walletAddress}", getRewardsByWalletAddrHandlerFn(clientCtx, keeper.QueryRewardsByWalletAddr)).Methods("GET") + r.HandleFunc("/pot/slashing/{walletAddress}", getSlashingByWalletAddressHandlerFn(clientCtx, keeper.QuerySlashingByWalletAddr)).Methods("GET") r.HandleFunc("/pot/params", potParamsHandlerFn(clientCtx, keeper.QueryPotParams)).Methods("GET") } @@ -42,7 +42,7 @@ func potParamsHandlerFn(clientCtx client.Context, queryPath string) http.Handler } } -func getPotRewardsByEpochHandlerFn(clientCtx client.Context, queryPath string) http.HandlerFunc { +func getIndividualRewardsByEpochHandlerFn(clientCtx client.Context, queryPath string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // get and verify params _, page, limit, err := rest.ParseHTTPArgsWithLimit(r, 0) @@ -60,7 +60,7 @@ func getPotRewardsByEpochHandlerFn(clientCtx client.Context, queryPath string) h return } - params := types.NewQueryPotRewardsByEpochParams(page, limit, epoch) + params := types.NewQueryIndividualRewardsByEpochParams(page, limit, epoch) bz, err := cliCtx.LegacyAmino.MarshalJSON(params) if err != nil { rest.PostProcessResponse(w, cliCtx, err.Error()) @@ -111,13 +111,8 @@ func getVolumeReportHandlerFn(clientCtx client.Context, queryPath string) http.H } // GET request handler to query potRewards info by walletAddr -func getPotRewardsByWalletAddrHandlerFn(clientCtx client.Context, queryPath string) http.HandlerFunc { +func getRewardsByWalletAddrHandlerFn(clientCtx client.Context, queryPath string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - _, page, limit, err := rest.ParseHTTPArgsWithLimit(r, 0) - if err != nil { - rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) - return - } cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, clientCtx, r) if !ok { @@ -150,7 +145,7 @@ func getPotRewardsByWalletAddrHandlerFn(clientCtx client.Context, queryPath stri } } - params := types.NewQueryPotRewardsByWalletAddrParams(page, limit, walletAddr, queryHeight, queryEpoch) + params := types.NewQueryRewardsByWalletAddrParams(walletAddr, queryHeight, queryEpoch) bz, err := cliCtx.LegacyAmino.MarshalJSON(params) if err != nil { @@ -170,7 +165,7 @@ func getPotRewardsByWalletAddrHandlerFn(clientCtx client.Context, queryPath stri } } -func getPotSlashingByWalletAddressHandlerFn(clientCtx client.Context, queryPath string) http.HandlerFunc { +func getSlashingByWalletAddressHandlerFn(clientCtx client.Context, queryPath string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, clientCtx, r) if !ok { diff --git a/x/pot/keeper/querier.go b/x/pot/keeper/querier.go index 6beb4e6a..1d955fcc 100644 --- a/x/pot/keeper/querier.go +++ b/x/pot/keeper/querier.go @@ -4,21 +4,23 @@ import ( "fmt" "strconv" - "github.com/cosmos/cosmos-sdk/client" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/stratosnet/stratos-chain/client" "github.com/stratosnet/stratos-chain/x/pot/types" - abci "github.com/tendermint/tendermint/abci/types" ) const ( - QueryVolumeReport = "query_volume_report" - QueryPotRewardsByReportEpoch = "query_pot_rewards_by_report_epoch" - QueryPotRewardsByWalletAddr = "query_pot_rewards_by_wallet_address" - QueryPotSlashingByWalletAddr = "query_pot_slashing_by_wallet_address" - QueryPotParams = "query_pot_params" - QueryDefaultLimit = 100 + QueryVolumeReport = "query_volume_report" + QueryIndividualRewardsByReportEpoch = "query_pot_individual_rewards_by_report_epoch" + QueryRewardsByWalletAddr = "query_pot_rewards_by_wallet_address" + QuerySlashingByWalletAddr = "query_pot_slashing_by_wallet_address" + QueryPotParams = "query_pot_params" + QueryDefaultLimit = 100 ) // NewQuerier creates a new querier for pot clients. @@ -27,12 +29,12 @@ func NewQuerier(k Keeper, legacyQuerierCdc *codec.LegacyAmino) sdk.Querier { switch path[0] { case QueryVolumeReport: return queryVolumeReport(ctx, req, k, legacyQuerierCdc) - case QueryPotRewardsByReportEpoch: - return queryPotRewardsByReportEpoch(ctx, req, k, legacyQuerierCdc) - case QueryPotRewardsByWalletAddr: - return queryPotRewardsByWalletAddress(ctx, req, k, legacyQuerierCdc) - case QueryPotSlashingByWalletAddr: - return queryPotSlashingByWalletAddress(ctx, req, k, legacyQuerierCdc) + case QueryIndividualRewardsByReportEpoch: + return queryIndividualRewardsByReportEpoch(ctx, req, k, legacyQuerierCdc) + case QueryRewardsByWalletAddr: + return queryRewardsByWalletAddress(ctx, req, k, legacyQuerierCdc) + case QuerySlashingByWalletAddr: + return querySlashingByWalletAddress(ctx, req, k, legacyQuerierCdc) case QueryPotParams: return getPotParams(ctx, req, k, legacyQuerierCdc) default: @@ -72,14 +74,14 @@ func queryVolumeReport(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacyQ return bz, nil } -// queryPotRewardsByReportEpoch fetches total rewards and owner individual rewards from traffic and mining. -func queryPotRewardsByReportEpoch(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacyQuerierCdc *codec.LegacyAmino) ([]byte, error) { - var params types.QueryPotRewardsByReportEpochParams +// queryPotRewardsByReportEpoch fetches individual rewards from traffic and mining pool. +func queryIndividualRewardsByReportEpoch(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacyQuerierCdc *codec.LegacyAmino) ([]byte, error) { + var params types.QueryIndividualRewardsByReportEpochParams err := legacyQuerierCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { return []byte{}, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } - potEpochRewards := k.getPotRewardsByReportEpoch(ctx, params) + potEpochRewards := k.getIndividualRewardsByReportEpoch(ctx, params) if len(potEpochRewards) < 1 { e := sdkerrors.Wrapf(types.ErrCannotFindReward, fmt.Sprintf("no Pot rewards information at epoch %s", params.Epoch.String())) return []byte{}, e @@ -91,56 +93,50 @@ func queryPotRewardsByReportEpoch(ctx sdk.Context, req abci.RequestQuery, k Keep return bz, nil } -func (k Keeper) getPotRewardsByReportEpoch(ctx sdk.Context, params types.QueryPotRewardsByReportEpochParams) (res []types.Reward) { +func (k Keeper) getIndividualRewardsByReportEpoch(ctx sdk.Context, params types.QueryIndividualRewardsByReportEpochParams) (res []types.Reward) { matureEpoch := params.Epoch.Add(sdk.NewInt(k.MatureEpoch(ctx))) + start, end := client.Paginate(params.Page, params.Limit, QueryDefaultLimit) + if start < 0 || end < 0 { + return nil + } + + index := 0 k.IteratorIndividualReward(ctx, matureEpoch, func(walletAddress sdk.AccAddress, individualReward types.Reward) (stop bool) { if !((individualReward.RewardFromMiningPool.Empty() || individualReward.RewardFromMiningPool.IsZero()) && (individualReward.RewardFromTrafficPool.Empty() || individualReward.RewardFromTrafficPool.IsZero())) { - res = append(res, individualReward) + if index >= end { + return true + } + if index >= start && index < end { + res = append(res, individualReward) + } + index++ } return false }) - start, end := client.Paginate(len(res), params.Page, params.Limit, QueryDefaultLimit) - if start < 0 || end < 0 { - return nil - } else { - res = res[start:end] - return res - } + return res } -func (k Keeper) getPotRewardsByWalletAddressAndEpoch(ctx sdk.Context, params types.QueryPotRewardsByWalletAddrParams) (res []types.Reward) { - matureEpoch := params.Epoch.Add(sdk.NewInt(k.MatureEpoch(ctx))) - - reward, found := k.GetIndividualReward(ctx, params.WalletAddr, matureEpoch) - if found { - res = append(res, reward) - } - - start, end := client.Paginate(len(res), params.Page, params.Limit, QueryDefaultLimit) - if start < 0 || end < 0 { - return nil - } else { - res = res[start:end] - return res - } -} - -func queryPotRewardsByWalletAddress(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacyQuerierCdc *codec.LegacyAmino) ([]byte, error) { - var params types.QueryPotRewardsByWalletAddrParams +// When param "Epoch" not exists: Returns wallet_address, mature_total & immature_total +// When Param "Epoch" exists: Returns walletAddress & individual_reward at that epoch +func queryRewardsByWalletAddress(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacyQuerierCdc *codec.LegacyAmino) ([]byte, error) { + var params types.QueryRewardsByWalletAddrParams err := legacyQuerierCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } + // param epoch exists if !params.Epoch.Equal(sdk.ZeroInt()) { - rewardsByByWalletAddressAndEpoch := k.getPotRewardsByWalletAddressAndEpoch(ctx, params) - if len(rewardsByByWalletAddressAndEpoch) < 1 { + matureEpoch := params.Epoch.Add(sdk.NewInt(k.MatureEpoch(ctx))) + rewardsByByWalletAddressAndEpoch, found := k.GetIndividualReward(ctx, params.WalletAddr, matureEpoch) + if !found { e := sdkerrors.Wrapf(types.ErrCannotFindReward, fmt.Sprintf("no Pot rewards information at epoch %s", params.Epoch.String())) return []byte{}, e } + bz, err := codec.MarshalJSONIndent(legacyQuerierCdc, rewardsByByWalletAddressAndEpoch) if err != nil { return []byte{}, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) @@ -148,6 +144,7 @@ func queryPotRewardsByWalletAddress(ctx sdk.Context, req abci.RequestQuery, k Ke return bz, nil } + // param epoch not exists immatureTotalReward := k.GetImmatureTotalReward(ctx, params.WalletAddr) matureTotalReward := k.GetMatureTotalReward(ctx, params.WalletAddr) reward := types.NewPotRewardInfo(params.WalletAddr, matureTotalReward, immatureTotalReward) @@ -159,7 +156,7 @@ func queryPotRewardsByWalletAddress(ctx sdk.Context, req abci.RequestQuery, k Ke return bz, nil } -func queryPotSlashingByWalletAddress(ctx sdk.Context, req abci.RequestQuery, k Keeper, _ *codec.LegacyAmino) ([]byte, error) { +func querySlashingByWalletAddress(ctx sdk.Context, req abci.RequestQuery, k Keeper, _ *codec.LegacyAmino) ([]byte, error) { addr, err := sdk.AccAddressFromBech32(string(req.Data)) if err != nil { return []byte(sdk.ZeroInt().String()), types.ErrUnknownAccountAddress diff --git a/x/pot/types/querier.go b/x/pot/types/querier.go index 0b1a6321..292cf6a9 100644 --- a/x/pot/types/querier.go +++ b/x/pot/types/querier.go @@ -4,18 +4,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// querier keys -const ( - QueryParams = "params" - QueryVolumeReportHash = "volume_report" -) - -//type PotRewardInfo struct { -// WalletAddress sdk.AccAddress -// MatureTotalReward sdk.Coins -// ImmatureTotalReward sdk.Coins -//} - // NewPotRewardInfo creates a new instance of PotRewardInfo func NewPotRewardInfo( walletAddress sdk.AccAddress, @@ -29,49 +17,31 @@ func NewPotRewardInfo( } } -type QueryPotRewardsByReportEpochParams struct { +type QueryIndividualRewardsByReportEpochParams struct { Page int Limit int Epoch sdk.Int - //WalletAddress sdk.AccAddress } -// NewQueryPotRewardsByEpochParams creates a new instance of QueryPotRewardsParams -func NewQueryPotRewardsByEpochParams(page, limit int, epoch sdk.Int) QueryPotRewardsByReportEpochParams { - return QueryPotRewardsByReportEpochParams{ +// NewQueryIndividualRewardsByEpochParams creates a new instance of QueryIndividualRewardsByReportEpochParams +func NewQueryIndividualRewardsByEpochParams(page, limit int, epoch sdk.Int) QueryIndividualRewardsByReportEpochParams { + return QueryIndividualRewardsByReportEpochParams{ Page: page, Limit: limit, Epoch: epoch, - //WalletAddress: walletAddress, } } -type QueryPotRewardsByWalletAddrParams struct { - Page int - Limit int +type QueryRewardsByWalletAddrParams struct { WalletAddr sdk.AccAddress Height int64 Epoch sdk.Int } -func NewQueryPotRewardsByWalletAddrParams(page, limit int, walletAddr sdk.AccAddress, height int64, epoch sdk.Int) QueryPotRewardsByWalletAddrParams { - return QueryPotRewardsByWalletAddrParams{ - Page: page, - Limit: limit, +func NewQueryRewardsByWalletAddrParams(walletAddr sdk.AccAddress, height int64, epoch sdk.Int) QueryRewardsByWalletAddrParams { + return QueryRewardsByWalletAddrParams{ WalletAddr: walletAddr, Height: height, Epoch: epoch, } } - -//type ReportInfo struct { -// Epoch sdk.Int -// Reference string -//} - -func NewReportInfo(epoch sdk.Int, reference string) ReportInfo { - return ReportInfo{ - Epoch: epoch.Int64(), - Reference: reference, - } -} From f9a6b6906b8fda858be26256797e95021c6f9857 Mon Sep 17 00:00:00 2001 From: jialbai Date: Fri, 20 Jan 2023 12:34:56 -0500 Subject: [PATCH 07/17] - qb1586: fix improper error handling in pot/endBlocker to print detailed error msg --- x/pot/abci.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/pot/abci.go b/x/pot/abci.go index 8ad1e09e..90c37c87 100644 --- a/x/pot/abci.go +++ b/x/pot/abci.go @@ -32,7 +32,7 @@ func EndBlocker(ctx sdk.Context, req abci.RequestEndBlock, k keeper.Keeper) []ab //distribute POT reward _, err := k.DistributePotReward(ctx, walletVolumes, epoch) if err != nil { - logger.Error("An error occurred while distributing the reward. ", err) + logger.Error("An error occurred while distributing the reward. ", "ErrMsg", err.Error()) } k.SetUnhandledReport(ctx, nil) From 5fb27c150e76e0e4b0f169e630751fdf3603ccb7 Mon Sep 17 00:00:00 2001 From: Xiong Date: Fri, 20 Jan 2023 15:22:32 -0500 Subject: [PATCH 08/17] fix: gwei denom not working with gas-price flag --- app/ante/fee.go | 149 ++++++++++++++++++++++++++++++++++++ app/ante/handler_options.go | 4 +- app/ante/interfaces.go | 15 ++++ 3 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 app/ante/fee.go diff --git a/app/ante/fee.go b/app/ante/fee.go new file mode 100644 index 00000000..9ce272e5 --- /dev/null +++ b/app/ante/fee.go @@ -0,0 +1,149 @@ +package ante + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +// MempoolFeeDecorator will check if the transaction's fee is at least as large +// as the local validator's minimum gasFee (defined in validator config). +// If fee is too low, decorator returns error and tx is rejected from mempool. +// Note this only applies when ctx.CheckTx = true +// If fee is high enough or not CheckTx, then call next AnteHandler +// CONTRACT: Tx must implement FeeTx to use MempoolFeeDecorator +type MempoolFeeDecorator struct{} + +func NewMempoolFeeDecorator() MempoolFeeDecorator { + return MempoolFeeDecorator{} +} + +func (mfd MempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { + feeTx, ok := tx.(sdk.FeeTx) + if !ok { + return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx") + } + + feeCoins, err := sdk.ParseCoinsNormalized(feeTx.GetFee().String()) + if err != nil { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "fee parsing error: %s", feeCoins) + } + gas := feeTx.GetGas() + + // Ensure that the provided fees meet a minimum threshold for the validator, + // if this is a CheckTx. This is only for local mempool purposes, and thus + // is only ran on check tx. + if ctx.IsCheckTx() && !simulate { + minGasPrices := ctx.MinGasPrices() + if !minGasPrices.IsZero() { + requiredFees := make(sdk.Coins, len(minGasPrices)) + + // Determine the required fees by multiplying each required minimum gas + // price by the gas limit, where fee = ceil(minGasPrice * gasLimit). + glDec := sdk.NewDec(int64(gas)) + for i, gp := range minGasPrices { + fee := gp.Amount.Mul(glDec) + requiredFees[i] = sdk.NewCoin(gp.Denom, fee.Ceil().RoundInt()) + } + + if !feeCoins.IsAnyGTE(requiredFees) { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees) + } + } + } + + return next(ctx, tx, simulate) +} + +// DeductFeeDecorator deducts fees from the first signer of the tx +// If the first signer does not have the funds to pay for the fees, return with InsufficientFunds error +// Call next AnteHandler if fees successfully deducted +// CONTRACT: Tx must implement FeeTx interface to use DeductFeeDecorator +type DeductFeeDecorator struct { + ak AccountKeeper + bankKeeper types.BankKeeper + feegrantKeeper FeegrantKeeper +} + +func NewDeductFeeDecorator(ak AccountKeeper, bk types.BankKeeper, fk FeegrantKeeper) DeductFeeDecorator { + return DeductFeeDecorator{ + ak: ak, + bankKeeper: bk, + feegrantKeeper: fk, + } +} + +func (dfd DeductFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { + feeTx, ok := tx.(sdk.FeeTx) + if !ok { + return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx") + } + + if addr := dfd.ak.GetModuleAddress(types.FeeCollectorName); addr == nil { + return ctx, fmt.Errorf("fee collector module account (%s) has not been set", types.FeeCollectorName) + } + + fee, err := sdk.ParseCoinsNormalized(feeTx.GetFee().String()) + if err != nil { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "fee parsing error: %s", fee) + } + feePayer := feeTx.FeePayer() + feeGranter := feeTx.FeeGranter() + + deductFeesFrom := feePayer + + // if feegranter set deduct fee from feegranter account. + // this works with only when feegrant enabled. + if feeGranter != nil { + if dfd.feegrantKeeper == nil { + return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "fee grants are not enabled") + } else if !feeGranter.Equals(feePayer) { + err := dfd.feegrantKeeper.UseGrantedFees(ctx, feeGranter, feePayer, fee, tx.GetMsgs()) + if err != nil { + return ctx, sdkerrors.Wrapf(err, "%s not allowed to pay fees from %s", feeGranter, feePayer) + } + } + + deductFeesFrom = feeGranter + } + + deductFeesFromAcc := dfd.ak.GetAccount(ctx, deductFeesFrom) + if deductFeesFromAcc == nil { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "fee payer address: %s does not exist", deductFeesFrom) + } + + // deduct the fees + if !fee.IsZero() { + err = DeductFees(dfd.bankKeeper, ctx, deductFeesFromAcc, fee) + if err != nil { + return ctx, err + } + } + + events := sdk.Events{ + sdk.NewEvent( + sdk.EventTypeTx, + sdk.NewAttribute(sdk.AttributeKeyFee, fee.String()), + sdk.NewAttribute(sdk.AttributeKeyFeePayer, deductFeesFrom.String()), + ), + } + ctx.EventManager().EmitEvents(events) + + return next(ctx, tx, simulate) +} + +// DeductFees deducts fees from the given account. +func DeductFees(bankKeeper types.BankKeeper, ctx sdk.Context, acc types.AccountI, fees sdk.Coins) error { + if !fees.IsValid() { + return sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "invalid fee amount: %s", fees) + } + + err := bankKeeper.SendCoinsFromAccountToModule(ctx, acc.GetAddress(), types.FeeCollectorName, fees) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error()) + } + + return nil +} diff --git a/app/ante/handler_options.go b/app/ante/handler_options.go index bada4e11..2c122484 100644 --- a/app/ante/handler_options.go +++ b/app/ante/handler_options.go @@ -61,12 +61,12 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler { RejectMessagesDecorator{}, // reject MsgEthereumTxs ante.NewSetUpContextDecorator(), ante.NewRejectExtensionOptionsDecorator(), - ante.NewMempoolFeeDecorator(), + NewMempoolFeeDecorator(), ante.NewValidateBasicDecorator(), ante.NewTxTimeoutHeightDecorator(), ante.NewValidateMemoDecorator(options.AccountKeeper), ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper), - ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper), + NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper), // SetPubKeyDecorator must be called before all signature verification decorators ante.NewSetPubKeyDecorator(options.AccountKeeper), ante.NewValidateSigCountDecorator(options.AccountKeeper), diff --git a/app/ante/interfaces.go b/app/ante/interfaces.go index 877c2674..89369928 100644 --- a/app/ante/interfaces.go +++ b/app/ante/interfaces.go @@ -5,6 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/tx" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -15,6 +16,20 @@ import ( evmtypes "github.com/stratosnet/stratos-chain/x/evm/types" ) +// AccountKeeper defines the contract needed for AccountKeeper related APIs. +// Interface provides support to use non-sdk AccountKeeper for AnteHandler's decorators. +type AccountKeeper interface { + GetParams(ctx sdk.Context) (params authtypes.Params) + GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI + SetAccount(ctx sdk.Context, acc authtypes.AccountI) + GetModuleAddress(moduleName string) sdk.AccAddress +} + +// FeegrantKeeper defines the expected feegrant keeper. +type FeegrantKeeper interface { + UseGrantedFees(ctx sdk.Context, granter, grantee sdk.AccAddress, fee sdk.Coins, msgs []sdk.Msg) error +} + // EVMKeeper defines the expected keeper interface used on the Eth AnteHandler type EVMKeeper interface { statedb.Keeper From cc6d6f013c0c3e0b3e80d3e606dbfd4300f8c318 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Dumais Date: Fri, 20 Jan 2023 16:30:37 -0500 Subject: [PATCH 09/17] chore/QB-1578 Update btcd dependencies --- crypto/hd/algorithm.go | 2 +- go.mod | 84 +++++----- go.sum | 342 ++++++++++++++--------------------------- 3 files changed, 160 insertions(+), 268 deletions(-) diff --git a/crypto/hd/algorithm.go b/crypto/hd/algorithm.go index f830124e..fdc7faab 100644 --- a/crypto/hd/algorithm.go +++ b/crypto/hd/algorithm.go @@ -1,8 +1,8 @@ package hd import ( + "github.com/btcsuite/btcd/btcutil/hdkeychain" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcutil/hdkeychain" "github.com/tyler-smith/go-bip39" "github.com/ethereum/go-ethereum/accounts" diff --git a/go.mod b/go.mod index c2456ce1..0945afe3 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,13 @@ module github.com/stratosnet/stratos-chain go 1.18 require ( - github.com/btcsuite/btcd v0.22.1 - github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce + github.com/btcsuite/btcd v0.23.4 + github.com/btcsuite/btcd/btcutil v1.1.2 github.com/cosmos/cosmos-sdk v0.45.9 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/ibc-go/v3 v3.0.0 github.com/davecgh/go-spew v1.1.1 - github.com/ethereum/go-ethereum v1.10.16 + github.com/ethereum/go-ethereum v1.10.26 github.com/gogo/protobuf v1.3.3 github.com/golang/protobuf v1.5.2 github.com/gorilla/mux v1.8.0 @@ -22,16 +22,16 @@ require ( github.com/regen-network/cosmos-proto v0.3.1 github.com/rs/cors v1.8.2 github.com/spf13/cast v1.5.0 - github.com/spf13/cobra v1.5.0 + github.com/spf13/cobra v1.6.0 github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.12.0 - github.com/stretchr/testify v1.8.0 - github.com/tendermint/tendermint v0.34.21 + github.com/spf13/viper v1.14.0 + github.com/stretchr/testify v1.8.1 + github.com/tendermint/tendermint v0.34.25-0.20221221220620-936221e0a8d9 github.com/tendermint/tm-db v0.6.7 github.com/tyler-smith/go-bip39 v1.1.0 - google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b - google.golang.org/grpc v1.48.0 - google.golang.org/protobuf v1.28.0 + google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e + google.golang.org/grpc v1.50.1 + google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 gopkg.in/yaml.v2 v2.4.0 ) @@ -44,32 +44,33 @@ require ( github.com/VictoriaMetrics/fastcache v1.6.0 // indirect github.com/Workiva/go-datastructures v1.0.53 // indirect github.com/allegro/bigcache v1.2.1 // indirect - github.com/armon/go-metrics v0.3.10 // indirect + github.com/armon/go-metrics v0.4.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bgentry/speakeasy v0.1.0 // indirect + github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.1.1 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/coinbase/rosetta-sdk-go v0.7.0 // indirect - github.com/confio/ics23/go v0.7.0 // indirect + github.com/confio/ics23/go v0.9.0 // indirect github.com/cosmos/btcutil v1.0.4 // indirect github.com/cosmos/gorocksdb v1.2.0 // indirect - github.com/cosmos/iavl v0.19.3 // indirect - github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect - github.com/cosmos/ledger-go v0.9.2 // indirect + github.com/cosmos/iavl v0.19.4 // indirect + github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect github.com/creachadair/taskgroup v0.3.2 // indirect - github.com/danieljoos/wincred v1.0.2 // indirect + github.com/danieljoos/wincred v1.1.2 // indirect github.com/deckarep/golang-set v1.8.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/badger/v2 v2.2007.2 // indirect github.com/dgraph-io/ristretto v0.0.3 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/dustin/go-humanize v1.0.0 // indirect - github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect + github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/edsrzf/mmap-go v1.0.0 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect @@ -94,21 +95,21 @@ require ( github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/uint256 v1.2.0 // indirect - github.com/huin/goupnp v1.0.2 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/huin/goupnp v1.0.3 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect - github.com/klauspost/compress v1.15.9 // indirect + github.com/klauspost/compress v1.15.11 // indirect github.com/klauspost/cpuid/v2 v2.0.4 // indirect github.com/lib/pq v1.10.6 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/magiconair/properties v1.8.6 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect - github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect + github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/minio/sha256-simd v1.0.0 // indirect @@ -123,39 +124,39 @@ require ( github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/onsi/ginkgo v1.16.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.12.2 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.34.0 // indirect - github.com/prometheus/procfs v0.7.3 // indirect + github.com/prometheus/procfs v0.8.0 // indirect github.com/prometheus/tsdb v0.7.1 // indirect - github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rjeczalik/notify v0.9.1 // indirect github.com/rs/zerolog v1.27.0 // indirect - github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // 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/spf13/afero v1.8.2 // indirect + github.com/spf13/afero v1.9.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 // indirect - github.com/subosito/gotenv v1.4.0 // indirect + github.com/subosito/gotenv v1.4.1 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect - github.com/tendermint/btcd v0.1.1 // indirect - github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect github.com/tendermint/go-amino v0.16.0 // indirect + github.com/tidwall/btree v1.5.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect - github.com/zondax/hid v0.9.0 // indirect + github.com/zondax/hid v0.9.1 // indirect + github.com/zondax/ledger-go v0.14.1 // indirect go.etcd.io/bbolt v1.3.6 // indirect - golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect + golang.org/x/crypto v0.4.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/net v0.0.0-20220726230323-06994584191e // indirect - golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect - golang.org/x/sys v0.0.0-20220727055044-e65921a090b8 // indirect - golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect - golang.org/x/text v0.3.7 // indirect - gopkg.in/ini.v1 v1.66.6 // indirect + golang.org/x/net v0.4.0 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.3.0 // indirect + golang.org/x/term v0.3.0 // indirect + golang.org/x/text v0.5.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v3 v3.0.1 // indirect nhooyr.io/websocket v1.8.6 // indirect @@ -164,6 +165,7 @@ require ( replace ( github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 + github.com/cosmos/cosmos-sdk => github.com/stratosnet/cosmos-sdk v0.45.12-0.20230120193304-2764d97976b4 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 google.golang.org/grpc => google.golang.org/grpc v1.33.2 ) diff --git a/go.sum b/go.sum index 57aee8f5..4aecbda2 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,11 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= @@ -24,7 +22,6 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -37,7 +34,6 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.0.0-beta.2 h1:/BZRNzm8N4K4eWfK28dL4yescorxtO7YG1yun8fy+pI= filippo.io/edwards25519 v1.0.0-beta.2/go.mod h1:X+pm78QAUPtFLi1z9PYIlS/bdDnvbCOGKtZ+ACWEf7o= @@ -59,13 +55,12 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= -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.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= +github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -84,7 +79,6 @@ github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20201201074141-dd0ecada1be6/go.mod h1: github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -93,56 +87,51 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo= -github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.4.0 h1:yCQqn7dwca4ITXb+CbubHmedzaQYHhNhrEXLYUeEe8Q= +github.com/armon/go-metrics v0.4.0/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= -github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y= -github.com/aws/aws-sdk-go-v2/credentials v1.1.1/go.mod h1:mM2iIjwl7LULWtS6JCACyInboHirisUUdkBPoTHMOUo= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2/go.mod h1:3hGg3PpiEjHnrkrlasTfxFqUsZ2GCk/fMUn4CbKgSkM= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8= -github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4= -github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbEWkXs7QRTQpCLGaKIprQW0= -github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM= -github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2gVpmOtVTJZNodLdLQLn/KsJqFvXwnd/s= +github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= -github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0= github.com/btcsuite/btcd v0.0.0-20190315201642-aa6e0f35703c/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= -github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= -github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +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/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.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= +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.2 h1:XLMbX8JQEiwMcYft2EGi8zPUkoa0abKIU6/BJSRsjzQ= +github.com/btcsuite/btcd/btcutil v1.1.2/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +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/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= @@ -150,7 +139,6 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -171,14 +159,11 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= -github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coinbase/rosetta-sdk-go v0.7.0 h1:lmTO/JEpCvZgpbkOITL95rA80CPKb5CtMzLaqF2mCNg= github.com/coinbase/rosetta-sdk-go v0.7.0/go.mod h1:7nD3oBPIiHqhRprqvMgPoGxe/nyq3yftRmpsy29coWE= -github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= -github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= @@ -188,8 +173,6 @@ github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1 github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.4 h1:n7C2ngKXo7UC9gNyMNLbzqz7Asuf+7Qv4gnX/rOdQ44= github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/TvgUaxbU= -github.com/cosmos/cosmos-sdk v0.45.9 h1:Z4s1EZL/mfM8uSSZr8WmyEbWp4hqbWVI5sAIFR432KY= -github.com/cosmos/cosmos-sdk v0.45.9/go.mod h1:Z5M4TX7PsHNHlF/1XanI2DIpORQ+Q/st7oaeufEjnvU= github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 h1:iKclrn3YEOwk4jQHT2ulgzuXyxmzmPczUalMwW4XH9k= github.com/cosmos/cosmos-sdk/ics23/go v0.8.0/go.mod h1:2a4dBq88TUoqoWAU5eu0lGvpFP3wWDPgdHPargtyw30= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= @@ -197,27 +180,25 @@ github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y= github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= -github.com/cosmos/iavl v0.19.3 h1:cESO0OwTTxQm5rmyESKW+zESheDUYI7CcZDWWDwnuxg= -github.com/cosmos/iavl v0.19.3/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= +github.com/cosmos/iavl v0.19.4 h1:t82sN+Y0WeqxDLJRSpNd8YFX5URIrT+p8n6oJbJ2Dok= +github.com/cosmos/iavl v0.19.4/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= github.com/cosmos/ibc-go/v3 v3.0.0 h1:XUNplHVS51Q2gMnTFsFsH9QJ7flsovMamnltKbEgPQ4= github.com/cosmos/ibc-go/v3 v3.0.0/go.mod h1:Mb+1NXiPOLd+CPFlOC6BKeAUaxXlhuWenMmRiUiSmwY= github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 h1:DdzS1m6o/pCqeZ8VOAit/gyATedRgjvkVI+UCrLpyuU= github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8= -github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4= -github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY= -github.com/cosmos/ledger-go v0.9.2 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI= -github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI= +github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= +github.com/cosmos/ledger-cosmos-go v0.12.2/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= +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/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM= github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= -github.com/danieljoos/wincred v1.0.2 h1:zf4bhty2iLuwgjgpraD2E9UbvO+fe54XXGJbOwe23fU= github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U= -github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= +github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= +github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -225,9 +206,11 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= 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/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= 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= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/dgraph-io/badger/v2 v2.2007.2 h1:EjjK0KqwaFMlPin1ajhP943VPENHJdEz1KLIegjaI3k= @@ -236,37 +219,33 @@ github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KP github.com/dgraph-io/ristretto v0.0.3 h1:jh22xisGBjrEVnRZ1DVTpBVQm0Xndu8sMl0CWDzSIBI= github.com/dgraph-io/ristretto v0.0.3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= -github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b h1:HBah4D48ypg3J7Np4N+HY/ZR76fx3HEUGxDU6Uk39oQ= github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= +github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= +github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM= -github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc= -github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y= +github.com/ethereum/go-ethereum v1.10.26 h1:i/7d9RBBwiXCEuyduBQzJw/mKmnvzsN14jqBmytw72s= +github.com/ethereum/go-ethereum v1.10.26/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= @@ -277,28 +256,21 @@ github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8S github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= 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/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= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.7.0 h1:jGB9xAJQ12AIGNB4HguylppmDK1Am9ppF7XnGXXJuoU= -github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= -github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= -github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -318,8 +290,6 @@ github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNV github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= @@ -329,9 +299,7 @@ github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GO github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= @@ -344,11 +312,9 @@ github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/E github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0= github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic= -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-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 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= @@ -385,11 +351,9 @@ github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3/go.mod h1:/XxbfmMg github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -400,7 +364,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= @@ -424,7 +388,6 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -441,11 +404,9 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7 github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= @@ -466,7 +427,6 @@ github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoP github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= -github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -504,28 +464,18 @@ github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goupnp v1.0.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= -github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7mYlOw2LqY= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= -github.com/influxdata/influxdb v1.8.3/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI= -github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/influxdata/influxql v1.1.1-0.20200828144457-65d3ef77d385/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk= -github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= -github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= -github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= -github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19ybifQhZoQNF5D8= -github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= -github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= -github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= github.com/ipfs/go-cid v0.1.0 h1:YN33LQulcRHjfom/i25yoOZR4Telp1Hr/2RU3d0PnC0= github.com/ipfs/go-cid v0.1.0/go.mod h1:rH5/Xv83Rfy8Rw6xG+id3DYAMUVmem1MowoKwdXmN2o= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= @@ -534,10 +484,8 @@ github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+ github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jhump/protoreflect v1.12.1-0.20220721211354-060cc04fc18b h1:izTof8BKh/nE1wrKOrloNA5q4odOarjf+Xpe+4qow98= +github.com/jhump/protoreflect v1.13.1-0.20220928232736-101791cb1b4c h1:XImQJfpJLmGEEd8ll5yPVyL/aEvmgGHW4WYTyNseLOM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -553,49 +501,35 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -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.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= -github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= -github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c= +github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/cpuid/v2 v2.0.4 h1:g0I61F2K2DjRHz1cnxlkNSBIaePVoJIjjnHui8QHbiw= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= -github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= @@ -606,39 +540,33 @@ github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= +github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= @@ -654,11 +582,9 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= -github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -669,7 +595,6 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= @@ -696,6 +621,8 @@ github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/neilotoole/errgroup v0.1.5/go.mod h1:Q2nLGf+594h0CLBs/Mbg6qOr7GtqDK7C2S41udRnToE= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -720,12 +647,11 @@ github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= +github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= @@ -737,20 +663,17 @@ 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/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw= -github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI= +github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= +github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= -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 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.1.1/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= @@ -760,7 +683,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -784,7 +706,6 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T 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= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= @@ -800,21 +721,21 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx 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.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= 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= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= -github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg= github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM= github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= -github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -829,18 +750,17 @@ github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubr github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs= github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= +github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +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/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa h1:0U2s5loxrTy6/VgfVoLuVLFJcURKLH49ie0zSch7gh4= -github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= +github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= -github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= -github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= @@ -858,15 +778,15 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= -github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= +github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= 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.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= -github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= +github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI= +github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= 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= @@ -875,22 +795,24 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn 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.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= -github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU= +github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E= github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= +github.com/stratosnet/cosmos-sdk v0.45.12-0.20230120193304-2764d97976b4 h1:/bGD538eoeCGdGWx84/6gy/gDhs9/YNCSqntj5jLTEo= +github.com/stratosnet/cosmos-sdk v0.45.12-0.20230120193304-2764d97976b4/go.mod h1:MGnVQqzBiOFq62Jxxcl+NEwYjEJDyyKleBakfxsrNjg= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= 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.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -898,29 +820,26 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/subosito/gotenv v1.4.0 h1:yAzM1+SmVcz5R4tXGsNMu1jUl2aOJXoiWUCEwwnGrvs= -github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= +github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= -github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= -github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RMWx1aInLzndwxKalgi5rTqgfXxOxbEI= -github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/tendermint/tendermint v0.34.21 h1:UiGGnBFHVrZhoQVQ7EfwSOLuCtarqCSsRf8VrklqB7s= -github.com/tendermint/tendermint v0.34.21/go.mod h1:XDvfg6U7grcFTDx7VkzxnhazQ/bspGJAn4DZ6DcLLjQ= +github.com/tendermint/tendermint v0.34.25-0.20221221220620-936221e0a8d9 h1:qwG0fu6MPoP/nsYIneHs1t2zQEzG4ZGS+GIaG7/pj7U= +github.com/tendermint/tendermint v0.34.25-0.20221221220620-936221e0a8d9/go.mod h1:TCGT4eRe5OW979YKVTpFOM57B4YkN+7FSDWpsgzAGwY= github.com/tendermint/tm-db v0.6.7 h1:fE00Cbl0jayAoqlExN6oyQJ7fR/ZtoVOmvPJ//+shu8= github.com/tendermint/tm-db v0.6.7/go.mod h1:byQDzFkZV1syXr/ReXS808NxA2xvyuuVgXOJ/088L6I= +github.com/tidwall/btree v1.5.0 h1:iV0yVY/frd7r6qGBXfEYs7DH0gTDgrKTrDjS7xt/IyQ= +github.com/tidwall/btree v1.5.0/go.mod h1:LGm8L/DZjPLmeWGjv5kFrY8dL4uVhMmzmmLYmsObdKE= github.com/tidwall/gjson v1.6.7/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI= github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/sjson v1.1.4/go.mod h1:wXpKXu8CtDjKAZ+3DrKY5ROCorDFahq8l0tey/Lx1fg= -github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg= github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= @@ -939,25 +858,24 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y= github.com/vmihailenco/msgpack/v5 v5.1.4/go.mod h1:C5gboKD0TJPqWDTVTtrQNfRbiBwHZGo8UTqP/9/XvLI= github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= -github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= -github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= +github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c= +github.com/zondax/ledger-go v0.14.1/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= @@ -976,7 +894,6 @@ go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 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/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= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -996,18 +913,13 @@ golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8= +golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= @@ -1021,7 +933,6 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -1046,7 +957,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1090,15 +1001,13 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220726230323-06994584191e h1:wOQNKh1uuDGRnmgF0jDxh7ctgGy/3P4rYWQRVJD4/Yg= -golang.org/x/net v0.0.0-20220726230323-06994584191e/go.mod h1:AaygXjzTFtRAg2ttMY5RMuhpJ3cNnI0XpyFJD1iQRSM= +golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= 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= @@ -1121,8 +1030,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1133,7 +1042,6 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1144,7 +1052,6 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1155,7 +1062,6 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1176,7 +1082,6 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1191,44 +1096,40 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220727055044-e65921a090b8 h1:dyU22nBWzrmTQxtNrr4dzVOvaw35nUYE279vF9UmsI8= -golang.org/x/sys v0.0.0-20220727055044-e65921a090b8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc= -golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1253,7 +1154,6 @@ golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -1284,17 +1184,12 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= -gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -1329,7 +1224,6 @@ google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1337,7 +1231,6 @@ google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= @@ -1366,8 +1259,8 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b h1:SfSkJugek6xm7lWywqth4r2iTrYLpD8lOj1nMIIhMNM= -google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e h1:S9GbmC1iCgvbLyAokVCwiO6tVIrU9Y7c5oMx1V/ki/Y= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -1382,27 +1275,26 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 h1:KR8+MyP7/qOlV+8Af01LtjL04bu7on42eVsxT4EyBQk= +google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI= -gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= @@ -1427,11 +1319,9 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= From 7e7d42189558fbef0d23a2ad6b3e7fe1f5bdba02 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Dumais Date: Mon, 23 Jan 2023 20:20:52 -0500 Subject: [PATCH 10/17] chore/QB-1578 fix go-ethereum update --- go.mod | 2 +- go.sum | 4 ++-- x/evm/keeper/grpc_query.go | 2 +- x/evm/keeper/state_transition.go | 14 +++++++------- x/evm/types/chain_config.go | 2 +- x/evm/types/tracer.go | 10 +++++++++- x/sds/client/cli/tx.go | 2 +- 7 files changed, 22 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index 0945afe3..2d2878b2 100644 --- a/go.mod +++ b/go.mod @@ -165,7 +165,7 @@ require ( replace ( github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 - github.com/cosmos/cosmos-sdk => github.com/stratosnet/cosmos-sdk v0.45.12-0.20230120193304-2764d97976b4 + github.com/cosmos/cosmos-sdk => github.com/stratosnet/cosmos-sdk v0.45.12-0.20230124002546-fd8c3abd07d5 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 google.golang.org/grpc => google.golang.org/grpc v1.33.2 ) diff --git a/go.sum b/go.sum index 4aecbda2..f3ad16d0 100644 --- a/go.sum +++ b/go.sum @@ -802,8 +802,8 @@ github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70K github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= -github.com/stratosnet/cosmos-sdk v0.45.12-0.20230120193304-2764d97976b4 h1:/bGD538eoeCGdGWx84/6gy/gDhs9/YNCSqntj5jLTEo= -github.com/stratosnet/cosmos-sdk v0.45.12-0.20230120193304-2764d97976b4/go.mod h1:MGnVQqzBiOFq62Jxxcl+NEwYjEJDyyKleBakfxsrNjg= +github.com/stratosnet/cosmos-sdk v0.45.12-0.20230124002546-fd8c3abd07d5 h1:WjTdRjQkoPKDtp2gaGu9s/Cv5QC4ahRI9VRuex+XvQE= +github.com/stratosnet/cosmos-sdk v0.45.12-0.20230124002546-fd8c3abd07d5/go.mod h1:p8Nf05bzxH7rGhbEuC0L+GEX4Fwvq3MgYFbdTlprZLc= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= diff --git a/x/evm/keeper/grpc_query.go b/x/evm/keeper/grpc_query.go index 7bd8fb63..e18f5bdf 100644 --- a/x/evm/keeper/grpc_query.go +++ b/x/evm/keeper/grpc_query.go @@ -516,7 +516,7 @@ func (k *Keeper) traceTx( } // Construct the JavaScript tracer to execute with - if tracer, err = tracers.New(traceConfig.Tracer, tCtx); err != nil { + if tracer, err = tracers.New(traceConfig.Tracer, tCtx, nil); err != nil { return nil, 0, status.Error(codes.Internal, err.Error()) } diff --git a/x/evm/keeper/state_transition.go b/x/evm/keeper/state_transition.go index aa0cdfb4..9103d21a 100644 --- a/x/evm/keeper/state_transition.go +++ b/x/evm/keeper/state_transition.go @@ -176,7 +176,7 @@ func (k Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc { // ApplyTransaction runs and attempts to perform a state transition with the given transaction (i.e Message), that will // only be persisted (committed) to the underlying KVStore if the transaction does not fail. // -// Gas tracking +// # Gas tracking // // Ethereum consumes gas according to the EVM opcodes instead of general reads and writes to store. Because of this, the // state transition needs to ignore the SDK gas consumption mechanism defined by the GasKVStore and instead consume the @@ -302,18 +302,18 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t // If the message fails, the VM execution error with the reason will be returned to the client // and the transaction won't be committed to the store. // -// Reverted state +// # Reverted state // // The snapshot and rollback are supported by the `statedb.StateDB`. // -// Different Callers +// # Different Callers // // It's called in three scenarios: // 1. `ApplyTransaction`, in the transaction processing flow. // 2. `EthCall/EthEstimateGas` grpc query handler. // 3. Called by other native modules directly. // -// Prechecks and Preprocessing +// # Prechecks and Preprocessing // // All relevant state transition prechecks for the MsgEthereumTx are performed on the AnteHandler, // prior to running the transaction against the state. The prechecks run are the following: @@ -329,11 +329,11 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t // // 1. set up the initial access list (iff fork > Berlin) // -// Tracer parameter +// # Tracer parameter // // It should be a `vm.Tracer` object or nil, if pass `nil`, it'll create a default one based on keeper options. // -// Commit parameter +// # Commit parameter // // If commit is true, the `StateDB` will be committed, otherwise discarded. func (k *Keeper) ApplyMessageWithConfig(ctx sdk.Context, msg core.Message, tracer vm.EVMLogger, commit bool, cfg *types.EVMConfig, txConfig statedb.TxConfig) (*types.MsgEthereumTxResponse, error) { @@ -370,7 +370,7 @@ func (k *Keeper) ApplyMessageWithConfig(ctx sdk.Context, msg core.Message, trace // access list preparation is moved from ante handler to here, because it's needed when `ApplyMessage` is called // under contexts where ante handlers are not run, for example `eth_call` and `eth_estimateGas`. - if rules := cfg.ChainConfig.Rules(big.NewInt(ctx.BlockHeight()), cfg.ChainConfig.MergeForkBlock != nil); rules.IsBerlin { + if rules := cfg.ChainConfig.Rules(big.NewInt(ctx.BlockHeight()), cfg.ChainConfig.MergeNetsplitBlock != nil); rules.IsBerlin { stateDB.PrepareAccessList(msg.From(), msg.To(), vm.ActivePrecompiles(rules), msg.AccessList()) } diff --git a/x/evm/types/chain_config.go b/x/evm/types/chain_config.go index e6aa9319..c64742c4 100644 --- a/x/evm/types/chain_config.go +++ b/x/evm/types/chain_config.go @@ -31,7 +31,7 @@ func (cc ChainConfig) EthereumConfig() *params.ChainConfig { BerlinBlock: getBlockValue(cc.BerlinBlock), LondonBlock: getBlockValue(cc.LondonBlock), ArrowGlacierBlock: getBlockValue(cc.ArrowGlacierBlock), - MergeForkBlock: getBlockValue(cc.MergeForkBlock), + MergeNetsplitBlock: getBlockValue(cc.MergeForkBlock), TerminalTotalDifficulty: nil, Ethash: nil, Clique: nil, diff --git a/x/evm/types/tracer.go b/x/evm/types/tracer.go index 7b262489..ea22fd55 100644 --- a/x/evm/types/tracer.go +++ b/x/evm/types/tracer.go @@ -30,7 +30,7 @@ func NewTracer(tracer string, msg core.Message, cfg *params.ChainConfig, height switch tracer { case TracerAccessList: - preCompiles := vm.ActivePrecompiles(cfg.Rules(big.NewInt(height), cfg.MergeForkBlock != nil)) + preCompiles := vm.ActivePrecompiles(cfg.Rules(big.NewInt(height), cfg.MergeNetsplitBlock != nil)) return logger.NewAccessListTracer(msg.AccessList(), msg.From(), *msg.To(), preCompiles) case TracerJSON: return logger.NewJSONLogger(logCfg, os.Stderr) @@ -134,6 +134,14 @@ func NewNoOpTracer() *NoOpTracer { return &NoOpTracer{} } +// CaptureTxStart implements vm.Tracer interface +func (dt NoOpTracer) CaptureTxStart(gasLimit uint64) { +} + +// CaptureTxEnd implements vm.Tracer interface +func (dt NoOpTracer) CaptureTxEnd(restGas uint64) { +} + // CaptureStart implements vm.Tracer interface func (dt NoOpTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { } diff --git a/x/sds/client/cli/tx.go b/x/sds/client/cli/tx.go index 6e72594e..88451ade 100644 --- a/x/sds/client/cli/tx.go +++ b/x/sds/client/cli/tx.go @@ -81,7 +81,7 @@ func PrepayTxCmd() *cobra.Command { return err } - fromAddr, fromName, _, err := client.GetFromFields(cliCtx.Keyring, args[0], cliCtx.GenerateOnly) + fromAddr, fromName, _, err := client.GetFromFields(cliCtx, cliCtx.Keyring, args[0]) if err != nil { return err } From 95772e12cd7c820c7dcd72eeb0b952614750303f Mon Sep 17 00:00:00 2001 From: jialbai Date: Tue, 24 Jan 2023 12:00:19 -0500 Subject: [PATCH 11/17] - qb1596: fix eaten error in some rare cases during prepay --- x/sds/keeper/keeper.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/x/sds/keeper/keeper.go b/x/sds/keeper/keeper.go index 8dce98d5..a23aeefb 100644 --- a/x/sds/keeper/keeper.go +++ b/x/sds/keeper/keeper.go @@ -75,7 +75,7 @@ func (k Keeper) SetFileHash(ctx sdk.Context, fileHash []byte, fileInfo types.Fil // The remaining total Ozone limit [Lt] is the upper bound of the total Ozone that users can purchase from the Stratos blockchain. // [X] is the total amount of STOS token prepaid by user at time t // the total amount of Ozone the user gets = Lt * X / (S + Pt + X) -func (k Keeper) purchaseNozAndSubCoins(ctx sdk.Context, from sdk.AccAddress, amount sdk.Int) sdk.Int { +func (k Keeper) purchaseNozAndSubCoins(ctx sdk.Context, from sdk.AccAddress, amount sdk.Int) (sdk.Int, error) { St := k.RegisterKeeper.GetEffectiveTotalStake(ctx) Pt := k.RegisterKeeper.GetTotalUnissuedPrepay(ctx).Amount Lt := k.RegisterKeeper.GetRemainingOzoneLimit(ctx) @@ -90,14 +90,14 @@ func (k Keeper) purchaseNozAndSubCoins(ctx sdk.Context, from sdk.AccAddress, amo // send coins to total unissued prepay pool err := k.RegisterKeeper.SendCoinsFromAccount2TotalUnissuedPrepayPool(ctx, from, sdk.NewCoin(k.BondDenom(ctx), amount)) if err != nil { - return sdk.ZeroInt() + return sdk.ZeroInt(), err } // update remaining noz limit newRemainingOzoneLimit := Lt.Sub(purchased) k.RegisterKeeper.SetRemainingOzoneLimit(ctx, newRemainingOzoneLimit) - return purchased + return purchased, nil } func (k Keeper) simulatePurchaseNoz(ctx sdk.Context, amount sdk.Int) sdk.Int { @@ -123,9 +123,7 @@ func (k Keeper) Prepay(ctx sdk.Context, sender sdk.AccAddress, coins sdk.Coins) } prepay := coins.AmountOf(k.BondDenom(ctx)) - purchased := k.purchaseNozAndSubCoins(ctx, sender, prepay) - - return purchased, nil + return k.purchaseNozAndSubCoins(ctx, sender, prepay) } // IterateFileUpload Iterate over all uploaded files. From b36d134fa6ed1c28e82ecb69085e755a86de85a8 Mon Sep 17 00:00:00 2001 From: WangLiStratos Date: Thu, 26 Jan 2023 23:09:54 -0500 Subject: [PATCH 12/17] updatestake to restore sp's ppstore --- x/register/keeper/msg_server.go | 3 ++- x/register/keeper/resource_node.go | 16 ++++++++-------- x/register/types/events.go | 1 + 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/x/register/keeper/msg_server.go b/x/register/keeper/msg_server.go index 8d6ea4bc..ce281a77 100644 --- a/x/register/keeper/msg_server.go +++ b/x/register/keeper/msg_server.go @@ -321,7 +321,7 @@ func (k msgServer) HandleMsgUpdateResourceNodeStake(goCtx context.Context, msg * return &types.MsgUpdateResourceNodeStakeResponse{}, errors.New("invalid stake delta") } - ozoneLimitChange, completionTime, err := k.UpdateResourceNodeStake(ctx, networkAddr, ownerAddress, *msg.StakeDelta, msg.IncrStake) + ozoneLimitChange, completionTime, node, err := k.UpdateResourceNodeStake(ctx, networkAddr, ownerAddress, *msg.StakeDelta, msg.IncrStake) if err != nil { return nil, sdkerrors.Wrap(types.ErrUpdateResourceNodeStake, err.Error()) } @@ -333,6 +333,7 @@ func (k msgServer) HandleMsgUpdateResourceNodeStake(goCtx context.Context, msg * sdk.NewAttribute(types.AttributeKeyNetworkAddress, msg.NetworkAddress), sdk.NewAttribute(types.AttributeKeyIncrStakeBool, strconv.FormatBool(msg.IncrStake)), sdk.NewAttribute(types.AttributeKeyStakeDelta, msg.StakeDelta.String()), + sdk.NewAttribute(types.AttributeKeyCurrentStake, sdk.NewCoin(k.BondDenom(ctx), node.Tokens).String()), sdk.NewAttribute(types.AttributeKeyOZoneLimitChanges, ozoneLimitChange.String()), sdk.NewAttribute(types.AttributeKeyUnbondingMatureTime, completionTime.Format(time.RFC3339)), ), diff --git a/x/register/keeper/resource_node.go b/x/register/keeper/resource_node.go index 91731066..f3c3eeec 100644 --- a/x/register/keeper/resource_node.go +++ b/x/register/keeper/resource_node.go @@ -317,36 +317,36 @@ func (k Keeper) UpdateResourceNode(ctx sdk.Context, description types.Descriptio } func (k Keeper) UpdateResourceNodeStake(ctx sdk.Context, networkAddr stratos.SdsAddress, ownerAddr sdk.AccAddress, - stakeDelta sdk.Coin, incrStake bool) (ozoneLimitChange sdk.Int, unbondingMatureTime time.Time, err error) { + stakeDelta sdk.Coin, incrStake bool) (ozoneLimitChange sdk.Int, unbondingMatureTime time.Time, resourcenode types.ResourceNode, err error) { blockTime := ctx.BlockHeader().Time node, found := k.GetResourceNode(ctx, networkAddr) if !found { - return sdk.ZeroInt(), blockTime, types.ErrNoResourceNodeFound + return sdk.ZeroInt(), blockTime, node, types.ErrNoResourceNodeFound } ownerAddrNode, _ := sdk.AccAddressFromBech32(node.GetOwnerAddress()) if !bytes.Equal(ownerAddrNode, ownerAddr) { - return sdk.ZeroInt(), blockTime, types.ErrInvalidOwnerAddr + return sdk.ZeroInt(), blockTime, node, types.ErrInvalidOwnerAddr } if incrStake { ozoneLimitChange, err := k.AddResourceNodeStake(ctx, node, stakeDelta) if err != nil { - return sdk.ZeroInt(), blockTime, err + return sdk.ZeroInt(), blockTime, node, err } - return ozoneLimitChange, blockTime, nil + return ozoneLimitChange, blockTime, node, nil } else { // if !incrStake if node.GetStatus() == stakingtypes.Unbonding { - return sdk.ZeroInt(), blockTime, types.ErrUnbondingNode + return sdk.ZeroInt(), blockTime, node, types.ErrUnbondingNode } ozoneLimitChange, completionTime, err := k.UnbondResourceNode(ctx, node, stakeDelta.Amount) if err != nil { - return sdk.ZeroInt(), blockTime, err + return sdk.ZeroInt(), blockTime, node, err } - return ozoneLimitChange, completionTime, nil + return ozoneLimitChange, completionTime, node, nil } } diff --git a/x/register/types/events.go b/x/register/types/events.go index 5cdc7957..89b1dca5 100644 --- a/x/register/types/events.go +++ b/x/register/types/events.go @@ -30,6 +30,7 @@ const ( AttributeKeyOZoneLimitChanges = "ozone_limit_changes" AttributeKeyInitialStake = "initial_stake" + AttributeKeyCurrentStake = "current_stake" AttributeKeyStakeDelta = "stake_delta" AttributeKeyStakeToRemove = "stake_to_remove" AttributeKeyIncrStakeBool = "incr_stake" From 5578b4469f797bfb3b3879c1341e1a16463f4fcb Mon Sep 17 00:00:00 2001 From: Marc-Antoine Dumais Date: Mon, 30 Jan 2023 16:43:24 -0500 Subject: [PATCH 13/17] test/QB-1603 Fix unit tests --- .github/workflows/pull-request | 20 ++ Makefile | 6 + x/pot/app_test.go | 126 ++++++------ x/register/types/resource_node.go | 2 +- x/sds/oz_price_test.go | 325 +++++++++++++++--------------- 5 files changed, 252 insertions(+), 227 deletions(-) create mode 100644 .github/workflows/pull-request diff --git a/.github/workflows/pull-request b/.github/workflows/pull-request new file mode 100644 index 00000000..c786e765 --- /dev/null +++ b/.github/workflows/pull-request @@ -0,0 +1,20 @@ +name: Go + +on: [pull_request] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: 1.18 + + - name: Build + run: go build -v ./... + + - name: Test + run: go test ./... \ No newline at end of file diff --git a/Makefile b/Makefile index e94447ce..797d8e9d 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,12 @@ build-windows: go.sum clean: rm -rf $(BUILDDIR)/ +coverage: + go test ./... -coverprofile cover.out -coverpkg=./... + go tool cover -html cover.out -o cover.html + go tool cover -func cover.out | grep total: + rm cover.out + ############################################################################### ### Localnet ### ############################################################################### diff --git a/x/pot/app_test.go b/x/pot/app_test.go index cff6aa48..ff1c7d9e 100644 --- a/x/pot/app_test.go +++ b/x/pot/app_test.go @@ -122,7 +122,7 @@ var ( valConsPrivKey1 = ed25519.GenPrivKey() valConsPubk1 = valConsPrivKey1.PubKey() - valInitialStake = sdk.NewInt(15 * stos2wei) + valInitialStake = sdk.NewInt(5 * stos2wei) ) // initialize data of volume report @@ -242,7 +242,7 @@ func TestPotVolumeReportMsgs(t *testing.T) { /********************* test slashing msg when i==2 *********************/ if i == 2 { - println("********************************* Deliver Slashing Tx START ********************************************") + t.Log("********************************* Deliver Slashing Tx START ********************************************") slashingMsg := setupSlashingMsg() /********************* deliver tx *********************/ @@ -262,22 +262,22 @@ func TestPotVolumeReportMsgs(t *testing.T) { totalConsumedNoz := resNodeSlashingNOZAmt1.ToDec() slashingAmtCheck := potKeeper.GetTrafficReward(ctx, totalConsumedNoz) - println("slashingAmtSetup = " + slashingAmtSetup.String()) + t.Log("slashingAmtSetup = " + slashingAmtSetup.String()) require.Equal(t, slashingAmtSetup, slashingAmtCheck.TruncateInt()) - println("********************************* Deliver Slashing Tx END ********************************************") + t.Log("********************************* Deliver Slashing Tx END ********************************************") } - println("*****************************************************************************") - println("*") - println("* height = ", header.GetHeight()) - println("*") - println("*****************************************************************************") + t.Log("*****************************************************************************") + t.Log("*") + t.Log("* height = ", header.GetHeight()) + t.Log("*") + t.Log("*****************************************************************************") /********************* prepare tx data *********************/ volumeReportMsg := setupMsgVolumeReport(i + 1) lastTotalMinedToken := potKeeper.GetTotalMinedTokens(ctx) - println("last committed TotalMinedTokens = " + lastTotalMinedToken.String()) + t.Log("last committed TotalMinedTokens = " + lastTotalMinedToken.String()) epoch, ok := sdk.NewIntFromString(volumeReportMsg.Epoch.String()) require.Equal(t, ok, true) @@ -288,16 +288,16 @@ func TestPotVolumeReportMsgs(t *testing.T) { totalConsumedNoz := potKeeper.GetTotalConsumedNoz(volumeReportMsg.WalletVolumes).ToDec() /********************* print info *********************/ - println("epoch " + volumeReportMsg.Epoch.String()) + t.Log("epoch " + volumeReportMsg.Epoch.String()) S := registerKeeper.GetInitialGenesisStakeTotal(ctx).ToDec() Pt := registerKeeper.GetTotalUnissuedPrepay(ctx).Amount.ToDec() Y := totalConsumedNoz Lt := registerKeeper.GetRemainingOzoneLimit(ctx).ToDec() R := S.Add(Pt).Mul(Y).Quo(Lt.Add(Y)) - //println("R = (S + Pt) * Y / (Lt + Y)") - println("S=" + S.String() + "\nPt=" + Pt.String() + "\nY=" + Y.String() + "\nLt=" + Lt.String() + "\nR=" + R.String() + "\n") + //t.Log("R = (S + Pt) * Y / (Lt + Y)") + t.Log("S=" + S.String() + "\nPt=" + Pt.String() + "\nY=" + Y.String() + "\nLt=" + Lt.String() + "\nR=" + R.String() + "\n") - println("---------------------------") + t.Log("---------------------------") potKeeper.InitVariable(ctx) distributeGoal := types.InitDistributeGoal() distributeGoal, err := potKeeper.CalcTrafficRewardInTotal(ctx, distributeGoal, totalConsumedNoz) @@ -305,46 +305,46 @@ func TestPotVolumeReportMsgs(t *testing.T) { distributeGoal, err = potKeeper.CalcMiningRewardInTotal(ctx, distributeGoal) //for main net require.NoError(t, err) - println(distributeGoal.String()) + t.Log(distributeGoal.String()) - println("---------------------------") - println("distribute detail:") + t.Log("---------------------------") + t.Log("distribute detail:") rewardDetailMap := make(map[string]types.Reward) rewardDetailMap = potKeeper.CalcRewardForResourceNode(ctx, totalConsumedNoz, volumeReportMsg.WalletVolumes, distributeGoal, rewardDetailMap) rewardDetailMap = potKeeper.CalcRewardForMetaNode(ctx, distributeGoal, rewardDetailMap) - println("resource_wallet1: address = " + resOwner1.String()) - println(" miningReward = " + rewardDetailMap[resOwner1.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[resOwner1.String()].RewardFromTrafficPool.String()) + t.Log("resource_wallet1: address = " + resOwner1.String()) + t.Log(" miningReward = " + rewardDetailMap[resOwner1.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[resOwner1.String()].RewardFromTrafficPool.String()) - println("resource_wallet2: address = " + resOwner2.String()) - println(" miningReward = " + rewardDetailMap[resOwner2.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[resOwner2.String()].RewardFromTrafficPool.String()) + t.Log("resource_wallet2: address = " + resOwner2.String()) + t.Log(" miningReward = " + rewardDetailMap[resOwner2.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[resOwner2.String()].RewardFromTrafficPool.String()) - println("resource_wallet3: address = " + resOwner3.String()) - println(" miningReward = " + rewardDetailMap[resOwner3.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[resOwner3.String()].RewardFromTrafficPool.String()) + t.Log("resource_wallet3: address = " + resOwner3.String()) + t.Log(" miningReward = " + rewardDetailMap[resOwner3.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[resOwner3.String()].RewardFromTrafficPool.String()) - println("resource_wallet4: address = " + resOwner4.String()) - println(" miningReward = " + rewardDetailMap[resOwner4.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[resOwner4.String()].RewardFromTrafficPool.String()) + t.Log("resource_wallet4: address = " + resOwner4.String()) + t.Log(" miningReward = " + rewardDetailMap[resOwner4.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[resOwner4.String()].RewardFromTrafficPool.String()) - println("resource_wallet5: address = " + resOwner5.String()) - println(" miningReward = " + rewardDetailMap[resOwner5.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[resOwner5.String()].RewardFromTrafficPool.String()) + t.Log("resource_wallet5: address = " + resOwner5.String()) + t.Log(" miningReward = " + rewardDetailMap[resOwner5.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[resOwner5.String()].RewardFromTrafficPool.String()) - println("indexing_wallet1: address = " + idxOwner1.String()) - println(" miningReward = " + rewardDetailMap[idxOwner1.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[idxOwner1.String()].RewardFromTrafficPool.String()) + t.Log("indexing_wallet1: address = " + idxOwner1.String()) + t.Log(" miningReward = " + rewardDetailMap[idxOwner1.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[idxOwner1.String()].RewardFromTrafficPool.String()) - println("indexing_wallet2: address = " + idxOwner2.String()) - println(" miningReward = " + rewardDetailMap[idxOwner2.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[idxOwner2.String()].RewardFromTrafficPool.String()) + t.Log("indexing_wallet2: address = " + idxOwner2.String()) + t.Log(" miningReward = " + rewardDetailMap[idxOwner2.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[idxOwner2.String()].RewardFromTrafficPool.String()) - println("indexing_wallet3: address = " + idxOwner3.String()) - println(" miningReward = " + rewardDetailMap[idxOwner3.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[idxOwner3.String()].RewardFromTrafficPool.String()) - println("---------------------------") + t.Log("indexing_wallet3: address = " + idxOwner3.String()) + t.Log(" miningReward = " + rewardDetailMap[idxOwner3.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[idxOwner3.String()].RewardFromTrafficPool.String()) + t.Log("---------------------------") /********************* record data before delivering tx *********************/ lastFoundationAccBalance := bankKeeper.GetAllBalances(ctx, foundationAccountAddr) @@ -361,7 +361,7 @@ func TestPotVolumeReportMsgs(t *testing.T) { require.NotNil(t, feePoolAccAddr) feeCollectorToFeePoolAtBeginBlock := bankKeeper.GetBalance(ctx, feePoolAccAddr, potKeeper.BondDenom(ctx)) - println("--------------------------- deliver volumeReportMsg") + t.Log("--------------------------- deliver volumeReportMsg") _, _, err = app.SignCheckDeliver(t, txGen, stApp.BaseApp, header, []sdk.Msg{volumeReportMsg}, chainID, []uint64{ownerAccNum}, []uint64{ownerAccSeq}, true, true, idxOwnerPrivKey1) require.NoError(t, err) @@ -408,7 +408,7 @@ func deductSlashingAmt(ctx sdk.Context, coins sdk.Coins, slashing sdk.Coin) (ret return ret } -//for main net +// for main net func checkResult(t *testing.T, ctx sdk.Context, k potKeeper.Keeper, accountKeeper authkeeper.AccountKeeper, @@ -427,15 +427,15 @@ func checkResult(t *testing.T, ctx sdk.Context, newMatureEpoch := currentEpoch.Add(sdk.NewInt(k.MatureEpoch(ctx))) k.IteratorIndividualReward(ctx, newMatureEpoch, func(walletAddress sdk.AccAddress, individualReward types.Reward) (stop bool) { individualRewardTotal = individualRewardTotal.Add(individualReward.RewardFromTrafficPool...).Add(individualReward.RewardFromMiningPool...) - println("individualReward of [" + walletAddress.String() + "] = " + individualReward.String()) + t.Log("individualReward of [" + walletAddress.String() + "] = " + individualReward.String()) return false }) - println("---------------------------") + t.Log("---------------------------") k.IteratorMatureTotal(ctx, func(walletAddress sdk.AccAddress, matureTotal sdk.Coins) (stop bool) { - println("MatureTotal of [" + walletAddress.String() + "] = " + matureTotal.String()) + t.Log("MatureTotal of [" + walletAddress.String() + "] = " + matureTotal.String()) return false }) - println("---------------------------") + t.Log("---------------------------") feeCollectorAccAddr := accountKeeper.GetModuleAddress(authtypes.FeeCollectorName) require.NotNil(t, feeCollectorAccAddr) @@ -444,39 +444,39 @@ func checkResult(t *testing.T, ctx sdk.Context, newUnissuedPrepay := sdk.NewCoins(registerKeeper.GetTotalUnissuedPrepay(ctx)) newCommunityPool := sdk.NewCoins(sdk.NewCoin(k.BondDenom(ctx), k.DistrKeeper.GetFeePool(ctx).CommunityPool.AmountOf(k.BondDenom(ctx)).TruncateInt())) - println("resource node 1 initial slashingAmt = " + initialSlashingAmt.String()) + t.Log("resource node 1 initial slashingAmt = " + initialSlashingAmt.String()) currentSlashingAmt := registerKeeper.GetSlashing(ctx, resOwner1) - println("resource node 1 currentSlashingAmt = " + currentSlashingAmt.String()) + t.Log("resource node 1 currentSlashingAmt = " + currentSlashingAmt.String()) slashingDeducted := sdk.NewCoin(k.RewardDenom(ctx), initialSlashingAmt.Sub(currentSlashingAmt)) - println("resource node 1 slashing deducted = " + slashingDeducted.String()) + t.Log("resource node 1 slashing deducted = " + slashingDeducted.String()) matureTotal := k.GetMatureTotalReward(ctx, resOwner1) immatureTotal := k.GetImmatureTotalReward(ctx, resOwner1) - println("resource node 1 matureTotal = " + matureTotal.String()) - println("resource node 1 immatureTotal = " + immatureTotal.String()) + t.Log("resource node 1 matureTotal = " + matureTotal.String()) + t.Log("resource node 1 immatureTotal = " + immatureTotal.String()) // distribution module will send all tokens from "fee_collector" to "distribution" account in the BeginBlocker() method feeCollectorValChange := bankKeeper.GetAllBalances(ctx, feeCollectorAccAddr) - println("reward for validator send to fee_collector = " + feeCollectorValChange.String()) + t.Log("reward for validator send to fee_collector = " + feeCollectorValChange.String()) communityTaxChange := newCommunityPool.Sub(lastCommunityPool).Sub(sdk.NewCoins(feeCollectorToFeePoolAtBeginBlock)) - println("community tax change in community_pool = " + communityTaxChange.String()) - println("community_pool amount of wei = " + newCommunityPool.String()) + t.Log("community tax change in community_pool = " + communityTaxChange.String()) + t.Log("community_pool amount of wei = " + newCommunityPool.String()) rewardSrcChange := lastFoundationAccBalance. Sub(newFoundationAccBalance). Add(lastUnissuedPrepay). Sub(newUnissuedPrepay) - println("rewardSrcChange = " + rewardSrcChange.String()) + t.Log("rewardSrcChange = " + rewardSrcChange.String()) rewardDestChange := feeCollectorValChange. Add(individualRewardTotal...). Add(communityTaxChange...) - println("rewardDestChange = " + rewardDestChange.String()) + t.Log("rewardDestChange = " + rewardDestChange.String()) require.Equal(t, rewardSrcChange, rewardDestChange) - println("************************ slashing test***********************************") - println("slashing change = " + slashingDeducted.String()) + t.Log("************************ slashing test***********************************") + t.Log("slashing change = " + slashingDeducted.String()) upcomingMaturedIndividual := sdk.Coins{} individualReward, found := k.GetIndividualReward(ctx, resOwner1, currentEpoch) @@ -484,7 +484,7 @@ func checkResult(t *testing.T, ctx sdk.Context, tmp := individualReward.RewardFromTrafficPool.Add(individualReward.RewardFromMiningPool...) upcomingMaturedIndividual = deductSlashingAmt(ctx, tmp, slashingDeducted) } - println("upcomingMaturedIndividual = " + upcomingMaturedIndividual.String()) + t.Log("upcomingMaturedIndividual = " + upcomingMaturedIndividual.String()) // get mature total changes newMatureTotalOfResNode1 := k.GetMatureTotalReward(ctx, resOwner1) @@ -492,12 +492,12 @@ func checkResult(t *testing.T, ctx sdk.Context, if matureTotalOfResNode1Change == nil || matureTotalOfResNode1Change.IsAnyNegative() { matureTotalOfResNode1Change = sdk.Coins{} } - println("matureTotalOfResNode1Change = " + matureTotalOfResNode1Change.String()) + t.Log("matureTotalOfResNode1Change = " + matureTotalOfResNode1Change.String()) require.Equal(t, matureTotalOfResNode1Change.String(), upcomingMaturedIndividual.String()) totalRewardPoolAddr := accountKeeper.GetModuleAddress(types.TotalRewardPool) totalRewardPoolBalance := bankKeeper.GetAllBalances(ctx, totalRewardPoolAddr) - println("totalRewardPoolBalance = " + totalRewardPoolBalance.String()) + t.Log("totalRewardPoolBalance = " + totalRewardPoolBalance.String()) } func checkValidator(t *testing.T, app *app.NewApp, addr sdk.ValAddress, expFound bool) stakingtypes.Validator { diff --git a/x/register/types/resource_node.go b/x/register/types/resource_node.go index e2be33c3..87792b22 100644 --- a/x/register/types/resource_node.go +++ b/x/register/types/resource_node.go @@ -108,7 +108,7 @@ func (v ResourceNode) ConvertToString() string { Status: %s Tokens: %s Owner Address: %s - NodeType: %s + NodeType: %v Description: %s CreationTime: %s }`, v.GetNetworkAddress(), pubKey, v.GetSuspend(), v.GetStatus(), v.Tokens, diff --git a/x/sds/oz_price_test.go b/x/sds/oz_price_test.go index ed816c41..ce443f58 100644 --- a/x/sds/oz_price_test.go +++ b/x/sds/oz_price_test.go @@ -1,7 +1,6 @@ package sds_test import ( - "fmt" "math/rand" "os" "strconv" @@ -169,7 +168,7 @@ func TestPriceCurve(t *testing.T) { NozSupply: initialTotalStakesStore.ToDec().Quo(stakeNozRateInt.ToDec()).TruncateInt(), } - initFactorsBefore, _, _ = simulatePriceChange(&PriceChangeEvent{ + initFactorsBefore, _, _ = simulatePriceChange(t, &PriceChangeEvent{ stakeDelta: sdk.ZeroInt(), unissuedPrepayDelta: sdk.ZeroInt(), }, initFactorsBefore) @@ -192,9 +191,9 @@ func TestPriceCurve(t *testing.T) { stakeDelta: stakeDeltaChange.Mul(sdk.NewInt(int64(tempStakeSign))), unissuedPrepayDelta: unissuedPrepayDeltaChange.Mul(sdk.NewInt(int64(tempPrepaySign))), } - fmt.Printf("\nstakeDeltaOri: %d, unissuedPrepayDeltaOri: %d\n", stakeChangePerm[i], prepayChangePerm[i]) - fmt.Printf("\nstakeDelta: %v, unissuedPrepayDelta: %v\n", change.stakeDelta.String(), change.unissuedPrepayDelta.String()) - initFactorsBefore, _, _ = simulatePriceChange(change, initFactorsBefore) + t.Logf("\nstakeDeltaOri: %d, unissuedPrepayDeltaOri: %d\n", stakeChangePerm[i], prepayChangePerm[i]) + t.Logf("\nstakeDelta: %v, unissuedPrepayDelta: %v\n", change.stakeDelta.String(), change.unissuedPrepayDelta.String()) + initFactorsBefore, _, _ = simulatePriceChange(t, change, initFactorsBefore) } } @@ -258,7 +257,7 @@ func TestOzPriceChange(t *testing.T) { require.True(sdk.IntEq(t, valInitialStake, validator.BondedTokens())) _, nozSupply := registerKeeper.NozSupply(ctx) - nozPriceFactorsSeq0, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(ctx, registerKeeper, NozPriceFactors{ + nozPriceFactorsSeq0, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(t, ctx, registerKeeper, NozPriceFactors{ NOzonePrice: registerKeeper.CurrNozPrice(ctx), InitialTotalStakes: registerKeeper.GetInitialGenesisStakeTotal(ctx), EffectiveTotalStakes: registerKeeper.GetEffectiveTotalStake(ctx), @@ -269,7 +268,7 @@ func TestOzPriceChange(t *testing.T) { }) // start testing - println("\n********************************* Deliver Prepay Tx START ********************************************") + t.Log("\n********************************* Deliver Prepay Tx START ********************************************") prepayMsg := setupPrepayMsg() /********************* deliver tx *********************/ @@ -284,12 +283,12 @@ func TestOzPriceChange(t *testing.T) { stApp.BeginBlock(abci.RequestBeginBlock{Header: header}) ctx = stApp.BaseApp.NewContext(true, header) - nozPriceFactorsSeq1, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(ctx, registerKeeper, nozPriceFactorsSeq0) + nozPriceFactorsSeq1, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(t, ctx, registerKeeper, nozPriceFactorsSeq0) require.True(t, nozPricePercentage.GT(sdk.ZeroDec()), "noz price should increase after PREPAY") require.True(t, ozoneLimitPercentage.LT(sdk.ZeroDec()), "OzLimit should decrease after PREPAY") - println("********************************* Deliver Prepay Tx END ********************************************\n\n...\n[NEXT TEST CASE]") + t.Log("********************************* Deliver Prepay Tx END ********************************************\n\n...\n[NEXT TEST CASE]") - println("********************************* Deliver CreateResourceNode Tx START ********************************************") + t.Log("********************************* Deliver CreateResourceNode Tx START ********************************************") createResourceNodeMsg := setupMsgCreateResourceNode1() /********************* deliver tx *********************/ @@ -304,12 +303,12 @@ func TestOzPriceChange(t *testing.T) { stApp.BeginBlock(abci.RequestBeginBlock{Header: header}) ctx = stApp.BaseApp.NewContext(true, header) - nozPriceFactorsSeq2, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(ctx, registerKeeper, nozPriceFactorsSeq1) + nozPriceFactorsSeq2, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(t, ctx, registerKeeper, nozPriceFactorsSeq1) require.True(t, nozPricePercentage.Equal(sdk.ZeroDec()), "noz price shouldn't change after CreateResourceNode") require.True(t, ozoneLimitPercentage.Equal(sdk.ZeroDec()), "OzLimit shouldn't change after CreateResourceNode") - println("********************************* Deliver CreateResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") + t.Log("********************************* Deliver CreateResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") - println("********************************* Deliver UnsuspendResourceNode Tx (Slashing) START ********************************************") + t.Log("********************************* Deliver UnsuspendResourceNode Tx (Slashing) START ********************************************") unsuspendMsg := setupUnsuspendMsg() /********************* deliver tx *********************/ @@ -329,15 +328,15 @@ func TestOzPriceChange(t *testing.T) { totalConsumedNoz := sdk.ZeroInt().ToDec() slashingAmtCheck := potKeeper.GetTrafficReward(ctx, totalConsumedNoz) - println("slashingAmtSetup=" + slashingAmtSetup.String()) + t.Log("slashingAmtSetup=" + slashingAmtSetup.String()) require.Equal(t, slashingAmtSetup, slashingAmtCheck.TruncateInt()) - nozPriceFactorsSeq3, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(ctx, registerKeeper, nozPriceFactorsSeq2) + nozPriceFactorsSeq3, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(t, ctx, registerKeeper, nozPriceFactorsSeq2) require.True(t, nozPricePercentage.LT(sdk.ZeroDec()), "noz price should decrease after UnsuspendResourceNode") require.True(t, ozoneLimitPercentage.GT(sdk.ZeroDec()), "OzLimit should increase after UnsuspendResourceNode") - println("********************************* Deliver UnsuspendResourceNode Tx (Slashing) END ********************************************\n\n...\n[NEXT TEST CASE]") + t.Log("********************************* Deliver UnsuspendResourceNode Tx (Slashing) END ********************************************\n\n...\n[NEXT TEST CASE]") - println("********************************* Deliver SuspendResourceNode Tx (Slashing) START ********************************************") + t.Log("********************************* Deliver SuspendResourceNode Tx (Slashing) START ********************************************") slashingMsg := setupSlashingMsg() /********************* deliver tx *********************/ @@ -357,24 +356,24 @@ func TestOzPriceChange(t *testing.T) { //totalConsumedNoz = resNodeSlashingNOZAmt1.ToDec() // //slashingAmtCheck = potKeeper.GetTrafficReward(ctx, totalConsumedNoz) - //println("slashingAmtSetup=" + slashingAmtSetup.String()) + //t.Log("slashingAmtSetup=" + slashingAmtSetup.String()) //require.Equal(t, slashingAmtSetup, slashingAmtCheck.TruncateInt()) - nozPriceFactorsSeq4, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(ctx, registerKeeper, nozPriceFactorsSeq3) + nozPriceFactorsSeq4, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(t, ctx, registerKeeper, nozPriceFactorsSeq3) require.True(t, nozPricePercentage.GT(sdk.ZeroDec()), "noz price should increase after SlashResourceNode") require.True(t, ozoneLimitPercentage.LT(sdk.ZeroDec()), "OzLimit should decrease after SlashResourceNode") - _, nozPricePercentage42, ozoneLimitPercentage42 := printCurrNozPrice(ctx, registerKeeper, nozPriceFactorsSeq2) + _, nozPricePercentage42, ozoneLimitPercentage42 := printCurrNozPrice(t, ctx, registerKeeper, nozPriceFactorsSeq2) require.True(t, nozPricePercentage42.Equal(sdk.ZeroDec()), "noz price after SlashResourceNode should be same with the price when node hadn't been activated") require.True(t, ozoneLimitPercentage42.Equal(sdk.ZeroDec()), "OzLimit after SlashResourceNode should be same with the ozLimit when node hadn't been activated") - println("********************************* Deliver SuspendResourceNode Tx (Slashing) END ********************************************\n\n...\n[NEXT TEST CASE]") + t.Log("********************************* Deliver SuspendResourceNode Tx (Slashing) END ********************************************\n\n...\n[NEXT TEST CASE]") - println("********************************* Deliver VolumeReport Tx START ********************************************") + t.Log("********************************* Deliver VolumeReport Tx START ********************************************") /********************* prepare tx data *********************/ volumeReportMsg := setupMsgVolumeReport(1) lastTotalMinedToken := potKeeper.GetTotalMinedTokens(ctx) - println("last committed TotalMinedTokens = " + lastTotalMinedToken.String()) + t.Log("last committed TotalMinedTokens = " + lastTotalMinedToken.String()) epoch, ok := sdk.NewIntFromString(volumeReportMsg.Epoch.String()) require.Equal(t, ok, true) @@ -383,16 +382,16 @@ func TestOzPriceChange(t *testing.T) { require.True(t, potKeeper.GetTotalConsumedNoz(volumeReportMsg.WalletVolumes).Add(remaining).LTE(total), "remaining+consumed Noz exceeds total Noz supply") /********************* print info *********************/ - println("epoch " + volumeReportMsg.Epoch.String()) + t.Log("epoch " + volumeReportMsg.Epoch.String()) St := registerKeeper.GetEffectiveTotalStake(ctx).ToDec() Pt := registerKeeper.GetTotalUnissuedPrepay(ctx).Amount.ToDec() Y := totalConsumedNoz Lt := registerKeeper.GetRemainingOzoneLimit(ctx).ToDec() R := St.Add(Pt).Mul(Y).Quo(Lt.Add(Y)) - //println("R = (S + Pt) * Y / (Lt + Y)") - println("St=" + St.String() + "\nPt=" + Pt.String() + "\nY=" + Y.String() + "\nLt=" + Lt.String() + "\nR=" + R.String() + "\n") + //t.Log("R = (S + Pt) * Y / (Lt + Y)") + t.Log("St=" + St.String() + "\nPt=" + Pt.String() + "\nY=" + Y.String() + "\nLt=" + Lt.String() + "\nR=" + R.String() + "\n") - println("---------------------------") + t.Log("---------------------------") potKeeper.InitVariable(ctx) distributeGoal := pottypes.InitDistributeGoal() distributeGoal, err = potKeeper.CalcTrafficRewardInTotal(ctx, distributeGoal, totalConsumedNoz) @@ -400,47 +399,47 @@ func TestOzPriceChange(t *testing.T) { distributeGoal, err = potKeeper.CalcMiningRewardInTotal(ctx, distributeGoal) //for main net require.NoError(t, err) - println(distributeGoal.String()) + t.Log(distributeGoal.String()) - println("---------------------------") - println("distribute detail:") + t.Log("---------------------------") + t.Log("distribute detail:") distributeGoalBalance := distributeGoal rewardDetailMap := make(map[string]pottypes.Reward) rewardDetailMap = potKeeper.CalcRewardForResourceNode(ctx, totalConsumedNoz, volumeReportMsg.WalletVolumes, distributeGoalBalance, rewardDetailMap) rewardDetailMap = potKeeper.CalcRewardForMetaNode(ctx, distributeGoalBalance, rewardDetailMap) - println("resource_wallet1: address = " + resOwner1.String()) - println(" miningReward = " + rewardDetailMap[resOwner1.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[resOwner1.String()].RewardFromTrafficPool.String()) + t.Log("resource_wallet1: address = " + resOwner1.String()) + t.Log(" miningReward = " + rewardDetailMap[resOwner1.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[resOwner1.String()].RewardFromTrafficPool.String()) - println("resource_wallet2: address = " + resOwner2.String()) - println(" miningReward = " + rewardDetailMap[resOwner2.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[resOwner2.String()].RewardFromTrafficPool.String()) + t.Log("resource_wallet2: address = " + resOwner2.String()) + t.Log(" miningReward = " + rewardDetailMap[resOwner2.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[resOwner2.String()].RewardFromTrafficPool.String()) - println("resource_wallet3: address = " + resOwner3.String()) - println(" miningReward = " + rewardDetailMap[resOwner3.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[resOwner3.String()].RewardFromTrafficPool.String()) + t.Log("resource_wallet3: address = " + resOwner3.String()) + t.Log(" miningReward = " + rewardDetailMap[resOwner3.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[resOwner3.String()].RewardFromTrafficPool.String()) - println("resource_wallet4: address = " + resOwner4.String()) - println(" miningReward = " + rewardDetailMap[resOwner4.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[resOwner4.String()].RewardFromTrafficPool.String()) + t.Log("resource_wallet4: address = " + resOwner4.String()) + t.Log(" miningReward = " + rewardDetailMap[resOwner4.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[resOwner4.String()].RewardFromTrafficPool.String()) - println("resource_wallet5: address = " + resOwner5.String()) - println(" miningReward = " + rewardDetailMap[resOwner5.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[resOwner5.String()].RewardFromTrafficPool.String()) + t.Log("resource_wallet5: address = " + resOwner5.String()) + t.Log(" miningReward = " + rewardDetailMap[resOwner5.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[resOwner5.String()].RewardFromTrafficPool.String()) - println("indexing_wallet1: address = " + idxOwner1.String()) - println(" miningReward = " + rewardDetailMap[idxOwner1.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[idxOwner1.String()].RewardFromTrafficPool.String()) + t.Log("indexing_wallet1: address = " + idxOwner1.String()) + t.Log(" miningReward = " + rewardDetailMap[idxOwner1.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[idxOwner1.String()].RewardFromTrafficPool.String()) - println("indexing_wallet2: address = " + idxOwner2.String()) - println(" miningReward = " + rewardDetailMap[idxOwner2.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[idxOwner2.String()].RewardFromTrafficPool.String()) + t.Log("indexing_wallet2: address = " + idxOwner2.String()) + t.Log(" miningReward = " + rewardDetailMap[idxOwner2.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[idxOwner2.String()].RewardFromTrafficPool.String()) - println("indexing_wallet3: address = " + idxOwner3.String()) - println(" miningReward = " + rewardDetailMap[idxOwner3.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[idxOwner3.String()].RewardFromTrafficPool.String()) - println("---------------------------") + t.Log("indexing_wallet3: address = " + idxOwner3.String()) + t.Log(" miningReward = " + rewardDetailMap[idxOwner3.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[idxOwner3.String()].RewardFromTrafficPool.String()) + t.Log("---------------------------") /********************* record data before delivering tx *********************/ lastFoundationAccBalance := bankKeeper.GetAllBalances(ctx, foundationAccountAddr) @@ -485,12 +484,12 @@ func TestOzPriceChange(t *testing.T) { feeCollectorToFeePoolAtBeginBlock, ) - nozPriceFactorsSeq5, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(ctx, registerKeeper, nozPriceFactorsSeq4) + nozPriceFactorsSeq5, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(t, ctx, registerKeeper, nozPriceFactorsSeq4) require.True(t, nozPricePercentage.LT(sdk.ZeroDec()), "noz price should decrease after VolumeReport") require.True(t, ozoneLimitPercentage.GT(sdk.ZeroDec()), "OzLimit shouldn't change after VolumeReport") - println("********************************* Deliver VolumeReport Tx END ********************************************\n\n...\n[NEXT TEST CASE]") + t.Log("********************************* Deliver VolumeReport Tx END ********************************************\n\n...\n[NEXT TEST CASE]") - println("********************************* Deliver CreateResourceNode Tx START ********************************************") + t.Log("********************************* Deliver CreateResourceNode Tx START ********************************************") createResourceNodeMsg2 := setupMsgCreateResourceNode2() /********************* deliver tx *********************/ @@ -505,12 +504,12 @@ func TestOzPriceChange(t *testing.T) { stApp.BeginBlock(abci.RequestBeginBlock{Header: header}) ctx = stApp.BaseApp.NewContext(true, header) - nozPriceFactorsSeq6, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(ctx, registerKeeper, nozPriceFactorsSeq5) + nozPriceFactorsSeq6, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(t, ctx, registerKeeper, nozPriceFactorsSeq5) require.True(t, nozPricePercentage.Equal(sdk.ZeroDec()), "noz price shouldn't change after CreateResourceNode") require.True(t, ozoneLimitPercentage.Equal(sdk.ZeroDec()), "OzLimit shouldn't change after CreateResourceNode") - println("********************************* Deliver CreateResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") + t.Log("********************************* Deliver CreateResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") - println("********************************* Deliver CreateResourceNode Tx START ********************************************") + t.Log("********************************* Deliver CreateResourceNode Tx START ********************************************") createResourceNodeMsg3 := setupMsgCreateResourceNode3() /********************* deliver tx *********************/ @@ -525,12 +524,12 @@ func TestOzPriceChange(t *testing.T) { stApp.BeginBlock(abci.RequestBeginBlock{Header: header}) ctx = stApp.BaseApp.NewContext(true, header) - nozPriceFactorsSeq7, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(ctx, registerKeeper, nozPriceFactorsSeq6) + nozPriceFactorsSeq7, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(t, ctx, registerKeeper, nozPriceFactorsSeq6) require.True(t, nozPricePercentage.Equal(sdk.ZeroDec()), "noz price shouldn't change after CreateResourceNode") require.True(t, ozoneLimitPercentage.Equal(sdk.ZeroDec()), "OzLimit shouldn't change after CreateResourceNode") - println("********************************* Deliver CreateResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") + t.Log("********************************* Deliver CreateResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") - println("********************************* Deliver CreateResourceNode Tx START ********************************************") + t.Log("********************************* Deliver CreateResourceNode Tx START ********************************************") createResourceNodeMsg4 := setupMsgCreateResourceNode4() /********************* deliver tx *********************/ @@ -545,12 +544,12 @@ func TestOzPriceChange(t *testing.T) { stApp.BeginBlock(abci.RequestBeginBlock{Header: header}) ctx = stApp.BaseApp.NewContext(true, header) - nozPriceFactorsSeq8, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(ctx, registerKeeper, nozPriceFactorsSeq7) + nozPriceFactorsSeq8, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(t, ctx, registerKeeper, nozPriceFactorsSeq7) require.True(t, nozPricePercentage.Equal(sdk.ZeroDec()), "noz price shouldn't change after CreateResourceNode") require.True(t, ozoneLimitPercentage.Equal(sdk.ZeroDec()), "OzLimit shouldn't change after CreateResourceNode") - println("********************************* Deliver CreateResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") + t.Log("********************************* Deliver CreateResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") - println("********************************* Deliver CreateResourceNode Tx START ********************************************") + t.Log("********************************* Deliver CreateResourceNode Tx START ********************************************") createResourceNodeMsg5 := setupMsgCreateResourceNode5() /********************* deliver tx *********************/ @@ -565,10 +564,10 @@ func TestOzPriceChange(t *testing.T) { stApp.BeginBlock(abci.RequestBeginBlock{Header: header}) ctx = stApp.BaseApp.NewContext(true, header) - _, nozPricePercentage, ozoneLimitPercentage = printCurrNozPrice(ctx, registerKeeper, nozPriceFactorsSeq8) + _, nozPricePercentage, ozoneLimitPercentage = printCurrNozPrice(t, ctx, registerKeeper, nozPriceFactorsSeq8) require.True(t, nozPricePercentage.Equal(sdk.ZeroDec()), "noz price shouldn't change after CreateResourceNode") require.True(t, ozoneLimitPercentage.Equal(sdk.ZeroDec()), "OzLimit shouldn't change after CreateResourceNode") - println("********************************* Deliver CreateResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") + t.Log("********************************* Deliver CreateResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") } @@ -685,7 +684,7 @@ func setupMsgCreateResourceNode5() *registertypes.MsgCreateResourceNode { return createResourceNodeMsg } -func printCurrNozPrice(ctx sdk.Context, registerKeeper registerKeeper.Keeper, nozPriceFactorsBefore NozPriceFactors) (NozPriceFactors, sdk.Dec, sdk.Dec) { +func printCurrNozPrice(t *testing.T, ctx sdk.Context, registerKeeper registerKeeper.Keeper, nozPriceFactorsBefore NozPriceFactors) (NozPriceFactors, sdk.Dec, sdk.Dec) { nozPriceFactorsAfter := NozPriceFactors{} nozPriceFactorsAfter.InitialTotalStakes = registerKeeper.GetInitialGenesisStakeTotal(ctx) nozPriceFactorsAfter.EffectiveTotalStakes = registerKeeper.GetEffectiveTotalStake(ctx) @@ -710,14 +709,14 @@ func printCurrNozPrice(ctx sdk.Context, registerKeeper registerKeeper.Keeper, no //stakeAndPrepayPercentage := stakeAndPrepayDelta.Quo(nozPriceFactorsBefore.StakeAndPrepay) ozoneLimitPercentage := ozoneLimitDelta.ToDec().Quo(nozPriceFactorsBefore.OzoneLimit.ToDec()).MulInt(sdk.NewInt(100)) - println("===>>>>>>>>>>>>>> Current noz Price ===>>>>>>>>>>>>>>") - println("NOzonePrice: " + nozPriceFactorsAfter.NOzonePrice.String() + "(delta: " + nozPriceDelta.String() + ", " + nozPricePercentage.String()[:5] + "%)") - println("InitialTotalStakes: " + nozPriceFactorsAfter.InitialTotalStakes.String() + "(delta: " + initialTotalStakesDelta.String() + ")") - println("EffectiveTotalStakes: " + nozPriceFactorsAfter.EffectiveTotalStakes.String() + "(delta: " + effectiveTotalStakesDelta.String() + ")") - println("TotalUnissuedPrepay: " + nozPriceFactorsAfter.TotalUnissuedPrepay.String() + "(delta: " + totalUnissuedPrepayDelta.String() + ")") - println("InitialTotalStakes+TotalUnissuedPrepay: " + nozPriceFactorsAfter.StakeAndPrepay.String() + "(delta: " + stakeAndPrepayDelta.String() + ")") - println("OzoneLimit: " + nozPriceFactorsAfter.OzoneLimit.String() + "(delta: " + ozoneLimitDelta.String() + ", " + ozoneLimitPercentage.String()[:5] + "%)") - println("NozSupply: " + nozPriceFactorsAfter.NozSupply.String() + "(delta: " + nozSupplyDelta.String() + ")") + t.Log("===>>>>>>>>>>>>>> Current noz Price ===>>>>>>>>>>>>>>") + t.Log("NOzonePrice: " + nozPriceFactorsAfter.NOzonePrice.String() + "(delta: " + nozPriceDelta.String() + ", " + nozPricePercentage.String()[:5] + "%)") + t.Log("InitialTotalStakes: " + nozPriceFactorsAfter.InitialTotalStakes.String() + "(delta: " + initialTotalStakesDelta.String() + ")") + t.Log("EffectiveTotalStakes: " + nozPriceFactorsAfter.EffectiveTotalStakes.String() + "(delta: " + effectiveTotalStakesDelta.String() + ")") + t.Log("TotalUnissuedPrepay: " + nozPriceFactorsAfter.TotalUnissuedPrepay.String() + "(delta: " + totalUnissuedPrepayDelta.String() + ")") + t.Log("InitialTotalStakes+TotalUnissuedPrepay: " + nozPriceFactorsAfter.StakeAndPrepay.String() + "(delta: " + stakeAndPrepayDelta.String() + ")") + t.Log("OzoneLimit: " + nozPriceFactorsAfter.OzoneLimit.String() + "(delta: " + ozoneLimitDelta.String() + ", " + ozoneLimitPercentage.String()[:5] + "%)") + t.Log("NozSupply: " + nozPriceFactorsAfter.NozSupply.String() + "(delta: " + nozSupplyDelta.String() + ")") return nozPriceFactorsAfter, nozPricePercentage, ozoneLimitPercentage } @@ -754,14 +753,14 @@ func checkResult(t *testing.T, ctx sdk.Context, feeCollectorToFeePoolAtBeginBlock sdk.Coin) { currentSlashing := registerKeeper.GetSlashing(ctx, resNodeAddr2) - println("currentSlashing = " + currentSlashing.String()) + t.Log("currentSlashing = " + currentSlashing.String()) individualRewardTotal := sdk.Coins{} newMatureEpoch := currentEpoch.Add(sdk.NewInt(k.MatureEpoch(ctx))) k.IteratorIndividualReward(ctx, newMatureEpoch, func(walletAddress sdk.AccAddress, individualReward pottypes.Reward) (stop bool) { individualRewardTotal = individualRewardTotal.Add(individualReward.RewardFromTrafficPool...).Add(individualReward.RewardFromMiningPool...) - println("individualReward of [" + walletAddress.String() + "] = " + individualReward.String()) + t.Log("individualReward of [" + walletAddress.String() + "] = " + individualReward.String()) return false }) @@ -772,29 +771,29 @@ func checkResult(t *testing.T, ctx sdk.Context, newUnissuedPrepay := sdk.NewCoins(registerKeeper.GetTotalUnissuedPrepay(ctx)) slashingChange := slashingAmtSetup.Sub(registerKeeper.GetSlashing(ctx, resOwner1)) - println("resource node 1 slashing change = " + slashingChange.String()) + t.Log("resource node 1 slashing change = " + slashingChange.String()) matureTotal := k.GetMatureTotalReward(ctx, resOwner1) immatureTotal := k.GetImmatureTotalReward(ctx, resOwner1) - println("resource node 1 matureTotal = " + matureTotal.String()) - println("resource node 1 immatureTotal = " + immatureTotal.String()) + t.Log("resource node 1 matureTotal = " + matureTotal.String()) + t.Log("resource node 1 immatureTotal = " + immatureTotal.String()) rewardSrcChange := lastFoundationAccBalance. Sub(newFoundationAccBalance). Add(lastUnissuedPrepay). Sub(newUnissuedPrepay) - println("rewardSrcChange = " + rewardSrcChange.String()) + t.Log("rewardSrcChange = " + rewardSrcChange.String()) // distribution module will send all tokens from "fee_collector" to "distribution" account in the BeginBlocker() method feePoolValChange := bankKeeper.GetAllBalances(ctx, feePoolAccAddr) - println("reward send to validator fee pool = " + feePoolValChange.String()) + t.Log("reward send to validator fee pool = " + feePoolValChange.String()) rewardDestChange := feePoolValChange.Add(individualRewardTotal...) - println("rewardDestChange = " + rewardDestChange.String()) + t.Log("rewardDestChange = " + rewardDestChange.String()) //require.Equal(t, rewardSrcChange, rewardDestChange) - println("************************ slashing test***********************************") - println("slashing change = " + slashingChange.String()) + t.Log("************************ slashing test***********************************") + t.Log("slashing change = " + slashingChange.String()) upcomingMaturedIndividual := sdk.Coins{} individualReward, found := k.GetIndividualReward(ctx, resOwner1, currentEpoch) @@ -802,7 +801,7 @@ func checkResult(t *testing.T, ctx sdk.Context, tmp := individualReward.RewardFromTrafficPool.Add(individualReward.RewardFromMiningPool...) upcomingMaturedIndividual = deductSlashingAmt(ctx, tmp, slashingChange) } - println("upcomingMaturedIndividual = " + upcomingMaturedIndividual.String()) + t.Log("upcomingMaturedIndividual = " + upcomingMaturedIndividual.String()) // get mature total changes newMatureTotalOfResNode1 := k.GetMatureTotalReward(ctx, resOwner1) @@ -810,7 +809,7 @@ func checkResult(t *testing.T, ctx sdk.Context, if matureTotalOfResNode1Change == nil || matureTotalOfResNode1Change.IsAnyNegative() { matureTotalOfResNode1Change = sdk.Coins{} } - println("matureTotalOfResNode1Change = " + matureTotalOfResNode1Change.String()) + t.Log("matureTotalOfResNode1Change = " + matureTotalOfResNode1Change.String()) require.Equal(t, matureTotalOfResNode1Change.String(), upcomingMaturedIndividual.String()) } @@ -1067,7 +1066,7 @@ type PriceChangeEvent struct { unissuedPrepayDelta sdk.Int } -func simulatePriceChange(priceChangeEvent *PriceChangeEvent, nozPriceFactorsBefore *NozPriceFactors) (*NozPriceFactors, sdk.Dec, sdk.Dec) { +func simulatePriceChange(t *testing.T, priceChangeEvent *PriceChangeEvent, nozPriceFactorsBefore *NozPriceFactors) (*NozPriceFactors, sdk.Dec, sdk.Dec) { nozPriceFactorsAfter := &NozPriceFactors{} nozPriceFactorsAfter.InitialTotalStakes = nozPriceFactorsBefore.InitialTotalStakes nozPriceFactorsAfter.TotalUnissuedPrepay = nozPriceFactorsBefore.TotalUnissuedPrepay.Add(priceChangeEvent.unissuedPrepayDelta) @@ -1086,7 +1085,7 @@ func simulatePriceChange(priceChangeEvent *PriceChangeEvent, nozPriceFactorsBefo Mul(priceChangeEvent.unissuedPrepayDelta.ToDec()). Quo(nozPriceFactorsBefore.EffectiveTotalStakes.Add(nozPriceFactorsBefore.TotalUnissuedPrepay).Add(priceChangeEvent.unissuedPrepayDelta).ToDec()). TruncateInt() - //Sub(nozPriceFactorsBefore.OzoneLimit) + //Sub(nozPriceFactorsBefore.OzoneLimit) if priceChangeEvent.unissuedPrepayDelta.GT(sdk.ZeroInt()) { // positive value of prepay leads to limit decrease deltaNozLimit = deltaNozLimit.Sub(ozoneLimitChangeByPrepay) @@ -1116,14 +1115,14 @@ func simulatePriceChange(priceChangeEvent *PriceChangeEvent, nozPriceFactorsBefo //stakeAndPrepayPercentage := stakeAndPrepayDelta.Quo(nozPriceFactorsBefore.StakeAndPrepay) ozoneLimitPercentage := ozoneLimitDelta.ToDec().Quo(nozPriceFactorsBefore.OzoneLimit.ToDec()).MulInt(sdk.NewInt(100)) - println("===>>>>>>>>>>>>>> Current noz Price ===>>>>>>>>>>>>>>") - println("NOzonePrice: " + nozPriceFactorsAfter.NOzonePrice.String() + "(delta: " + nozPriceDelta.String() + ", " + nozPricePercentage.String()[:5] + "%)") - println("InitialTotalStakes: " + nozPriceFactorsAfter.InitialTotalStakes.String() + "(delta: " + initialTotalStakesDelta.String() + ")") - println("EffectiveTotalStakes: " + nozPriceFactorsAfter.EffectiveTotalStakes.String() + "(delta: " + effectiveTotalStakesDelta.String() + ")") - println("TotalUnissuedPrepay: " + nozPriceFactorsAfter.TotalUnissuedPrepay.String() + "(delta: " + totalUnissuedPrepayDelta.String() + ")") - println("InitialTotalStakes+TotalUnissuedPrepay: " + nozPriceFactorsAfter.StakeAndPrepay.String() + "(delta: " + stakeAndPrepayDelta.String() + ")") - println("OzoneLimit: " + nozPriceFactorsAfter.OzoneLimit.String() + "(delta: " + ozoneLimitDelta.String() + ", " + ozoneLimitPercentage.String()[:5] + "%)") - println("NozSupply: " + nozPriceFactorsAfter.NozSupply.String() + "(delta: " + nozSupplyDelta.String() + ")") + t.Log("===>>>>>>>>>>>>>> Current noz Price ===>>>>>>>>>>>>>>") + t.Log("NOzonePrice: " + nozPriceFactorsAfter.NOzonePrice.String() + "(delta: " + nozPriceDelta.String() + ", " + nozPricePercentage.String()[:5] + "%)") + t.Log("InitialTotalStakes: " + nozPriceFactorsAfter.InitialTotalStakes.String() + "(delta: " + initialTotalStakesDelta.String() + ")") + t.Log("EffectiveTotalStakes: " + nozPriceFactorsAfter.EffectiveTotalStakes.String() + "(delta: " + effectiveTotalStakesDelta.String() + ")") + t.Log("TotalUnissuedPrepay: " + nozPriceFactorsAfter.TotalUnissuedPrepay.String() + "(delta: " + totalUnissuedPrepayDelta.String() + ")") + t.Log("InitialTotalStakes+TotalUnissuedPrepay: " + nozPriceFactorsAfter.StakeAndPrepay.String() + "(delta: " + stakeAndPrepayDelta.String() + ")") + t.Log("OzoneLimit: " + nozPriceFactorsAfter.OzoneLimit.String() + "(delta: " + ozoneLimitDelta.String() + ", " + ozoneLimitPercentage.String()[:5] + "%)") + t.Log("NozSupply: " + nozPriceFactorsAfter.NozSupply.String() + "(delta: " + nozSupplyDelta.String() + ")") return nozPriceFactorsAfter, nozPricePercentage, ozoneLimitPercentage } @@ -1189,7 +1188,7 @@ func TestOzPriceChangePrepay(t *testing.T) { require.Equal(t, stakingtypes.Bonded, validator.Status) require.True(sdk.IntEq(t, valInitialStake, validator.BondedTokens())) _, nozSupply := registerKeeper.NozSupply(ctx) - nozPriceFactorsSeq0, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(ctx, registerKeeper, NozPriceFactors{ + nozPriceFactorsSeq0, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(t, ctx, registerKeeper, NozPriceFactors{ NOzonePrice: registerKeeper.CurrNozPrice(ctx), InitialTotalStakes: registerKeeper.GetInitialGenesisStakeTotal(ctx), EffectiveTotalStakes: registerKeeper.GetEffectiveTotalStake(ctx), @@ -1200,7 +1199,7 @@ func TestOzPriceChangePrepay(t *testing.T) { }) // start testing - println("\n********************************* Deliver Prepay Tx START ********************************************") + t.Log("\n********************************* Deliver Prepay Tx START ********************************************") priceBefore := nozPriceFactorsSeq0 priceAfter := nozPriceFactorsSeq0 @@ -1220,15 +1219,15 @@ func TestOzPriceChangePrepay(t *testing.T) { header = tmproto.Header{Height: stApp.LastBlockHeight() + 1, ChainID: chainID} stApp.BeginBlock(abci.RequestBeginBlock{Header: header}) ctx = stApp.BaseApp.NewContext(true, header) - priceAfter, nozPricePercentage, ozoneLimitPercentage = printCurrNozPrice(ctx, registerKeeper, priceBefore) + priceAfter, nozPricePercentage, ozoneLimitPercentage = printCurrNozPrice(t, ctx, registerKeeper, priceBefore) dataToExcel = append(dataToExcel, priceAfter) require.True(t, nozPricePercentage.GT(sdk.ZeroDec()), "noz price should increase after PREPAY") require.True(t, ozoneLimitPercentage.LT(sdk.ZeroDec()), "OzLimit should not change after PREPAY") - println("********************************* Deliver Prepay Tx END ********************************************\n\n...\n[NEXT TEST CASE]") + t.Log("********************************* Deliver Prepay Tx END ********************************************\n\n...\n[NEXT TEST CASE]") priceBefore = priceAfter } - exportToCSV(dataToExcel) + exportToCSV(t, dataToExcel) } func TestOzPriceChangeVolumeReport(t *testing.T) { @@ -1292,7 +1291,7 @@ func TestOzPriceChangeVolumeReport(t *testing.T) { require.Equal(t, stakingtypes.Bonded, validator.Status) require.True(sdk.IntEq(t, valInitialStake, validator.BondedTokens())) _, nozSupply := registerKeeper.NozSupply(ctx) - nozPriceFactorsSeq0, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(ctx, registerKeeper, NozPriceFactors{ + nozPriceFactorsSeq0, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(t, ctx, registerKeeper, NozPriceFactors{ NOzonePrice: registerKeeper.CurrNozPrice(ctx), InitialTotalStakes: registerKeeper.GetInitialGenesisStakeTotal(ctx), EffectiveTotalStakes: registerKeeper.GetEffectiveTotalStake(ctx), @@ -1303,7 +1302,7 @@ func TestOzPriceChangeVolumeReport(t *testing.T) { }) // start testing - println("\n********************************* Deliver Prepay Tx START ********************************************") + t.Log("\n********************************* Deliver Prepay Tx START ********************************************") priceBefore := nozPriceFactorsSeq0 priceAfter := nozPriceFactorsSeq0 @@ -1323,37 +1322,37 @@ func TestOzPriceChangeVolumeReport(t *testing.T) { header = tmproto.Header{Height: stApp.LastBlockHeight() + 1, ChainID: chainID} stApp.BeginBlock(abci.RequestBeginBlock{Header: header}) ctx = stApp.BaseApp.NewContext(true, header) - priceAfter, nozPricePercentage, ozoneLimitPercentage = printCurrNozPrice(ctx, registerKeeper, priceBefore) + priceAfter, nozPricePercentage, ozoneLimitPercentage = printCurrNozPrice(t, ctx, registerKeeper, priceBefore) dataToExcel = append(dataToExcel, priceAfter) require.True(t, nozPricePercentage.GT(sdk.ZeroDec()), "noz price should increase after PREPAY") require.True(t, ozoneLimitPercentage.LT(sdk.ZeroDec()), "OzLimit should decrease after PREPAY") - println("********************************* Deliver Prepay Tx END ********************************************\n\n...\n[NEXT TEST CASE]") + t.Log("********************************* Deliver Prepay Tx END ********************************************\n\n...\n[NEXT TEST CASE]") priceBefore = priceAfter } for i := 0; i < NUM_OF_SAMPLE; i++ { - println("********************************* Deliver VolumeReport Tx START ********************************************") + t.Log("********************************* Deliver VolumeReport Tx START ********************************************") /********************* prepare tx data *********************/ volumeReportMsg := setupMsgVolumeReport(int64(i + 1)) lastTotalMinedToken := potKeeper.GetTotalMinedTokens(ctx) - println("last committed TotalMinedTokens = " + lastTotalMinedToken.String()) + t.Log("last committed TotalMinedTokens = " + lastTotalMinedToken.String()) _, ok := sdk.NewIntFromString(volumeReportMsg.Epoch.String()) require.Equal(t, ok, true) totalConsumedNoz := potKeeper.GetTotalConsumedNoz(volumeReportMsg.WalletVolumes).ToDec() /********************* print info *********************/ - println("epoch " + volumeReportMsg.Epoch.String()) + t.Log("epoch " + volumeReportMsg.Epoch.String()) S := registerKeeper.GetInitialGenesisStakeTotal(ctx).ToDec() Pt := registerKeeper.GetTotalUnissuedPrepay(ctx).Amount.ToDec() Y := totalConsumedNoz Lt := registerKeeper.GetRemainingOzoneLimit(ctx).ToDec() R := S.Add(Pt).Mul(Y).Quo(Lt.Add(Y)) - //println("R = (S + Pt) * Y / (Lt + Y)") - println("S=" + S.String() + "\nPt=" + Pt.String() + "\nY=" + Y.String() + "\nLt=" + Lt.String() + "\nR=" + R.String() + "\n") + //t.Log("R = (S + Pt) * Y / (Lt + Y)") + t.Log("S=" + S.String() + "\nPt=" + Pt.String() + "\nY=" + Y.String() + "\nLt=" + Lt.String() + "\nR=" + R.String() + "\n") - println("---------------------------") + t.Log("---------------------------") potKeeper.InitVariable(ctx) distributeGoal := pottypes.InitDistributeGoal() distributeGoal, err := potKeeper.CalcTrafficRewardInTotal(ctx, distributeGoal, totalConsumedNoz) @@ -1361,46 +1360,46 @@ func TestOzPriceChangeVolumeReport(t *testing.T) { distributeGoal, err = potKeeper.CalcMiningRewardInTotal(ctx, distributeGoal) //for main net require.NoError(t, err) - println(distributeGoal.String()) + t.Log(distributeGoal.String()) - println("---------------------------") - println("distribute detail:") + t.Log("---------------------------") + t.Log("distribute detail:") rewardDetailMap := make(map[string]pottypes.Reward) rewardDetailMap = potKeeper.CalcRewardForResourceNode(ctx, totalConsumedNoz, volumeReportMsg.WalletVolumes, distributeGoal, rewardDetailMap) rewardDetailMap = potKeeper.CalcRewardForMetaNode(ctx, distributeGoal, rewardDetailMap) - println("resource_wallet1: address = " + resOwner1.String()) - println(" miningReward = " + rewardDetailMap[resOwner1.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[resOwner1.String()].RewardFromTrafficPool.String()) + t.Log("resource_wallet1: address = " + resOwner1.String()) + t.Log(" miningReward = " + rewardDetailMap[resOwner1.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[resOwner1.String()].RewardFromTrafficPool.String()) - println("resource_wallet2: address = " + resOwner2.String()) - println(" miningReward = " + rewardDetailMap[resOwner2.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[resOwner2.String()].RewardFromTrafficPool.String()) + t.Log("resource_wallet2: address = " + resOwner2.String()) + t.Log(" miningReward = " + rewardDetailMap[resOwner2.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[resOwner2.String()].RewardFromTrafficPool.String()) - println("resource_wallet3: address = " + resOwner3.String()) - println(" miningReward = " + rewardDetailMap[resOwner3.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[resOwner3.String()].RewardFromTrafficPool.String()) + t.Log("resource_wallet3: address = " + resOwner3.String()) + t.Log(" miningReward = " + rewardDetailMap[resOwner3.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[resOwner3.String()].RewardFromTrafficPool.String()) - println("resource_wallet4: address = " + resOwner4.String()) - println(" miningReward = " + rewardDetailMap[resOwner4.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[resOwner4.String()].RewardFromTrafficPool.String()) + t.Log("resource_wallet4: address = " + resOwner4.String()) + t.Log(" miningReward = " + rewardDetailMap[resOwner4.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[resOwner4.String()].RewardFromTrafficPool.String()) - println("resource_wallet5: address = " + resOwner5.String()) - println(" miningReward = " + rewardDetailMap[resOwner5.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[resOwner5.String()].RewardFromTrafficPool.String()) + t.Log("resource_wallet5: address = " + resOwner5.String()) + t.Log(" miningReward = " + rewardDetailMap[resOwner5.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[resOwner5.String()].RewardFromTrafficPool.String()) - println("indexing_wallet1: address = " + idxOwner1.String()) - println(" miningReward = " + rewardDetailMap[idxOwner1.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[idxOwner1.String()].RewardFromTrafficPool.String()) + t.Log("indexing_wallet1: address = " + idxOwner1.String()) + t.Log(" miningReward = " + rewardDetailMap[idxOwner1.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[idxOwner1.String()].RewardFromTrafficPool.String()) - println("indexing_wallet2: address = " + idxOwner2.String()) - println(" miningReward = " + rewardDetailMap[idxOwner2.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[idxOwner2.String()].RewardFromTrafficPool.String()) + t.Log("indexing_wallet2: address = " + idxOwner2.String()) + t.Log(" miningReward = " + rewardDetailMap[idxOwner2.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[idxOwner2.String()].RewardFromTrafficPool.String()) - println("indexing_wallet3: address = " + idxOwner3.String()) - println(" miningReward = " + rewardDetailMap[idxOwner3.String()].RewardFromMiningPool.String()) - println(" trafficReward = " + rewardDetailMap[idxOwner3.String()].RewardFromTrafficPool.String()) - println("---------------------------") + t.Log("indexing_wallet3: address = " + idxOwner3.String()) + t.Log(" miningReward = " + rewardDetailMap[idxOwner3.String()].RewardFromMiningPool.String()) + t.Log(" trafficReward = " + rewardDetailMap[idxOwner3.String()].RewardFromTrafficPool.String()) + t.Log("---------------------------") /********************* record data before delivering tx *********************/ _ = bankKeeper.GetAllBalances(ctx, foundationAccountAddr) @@ -1432,11 +1431,11 @@ func TestOzPriceChangeVolumeReport(t *testing.T) { header = tmproto.Header{Height: stApp.LastBlockHeight() + 1, ChainID: chainID} stApp.BeginBlock(abci.RequestBeginBlock{Header: header}) ctx = stApp.BaseApp.NewContext(true, header) - priceAfter, nozPricePercentage, ozoneLimitPercentage = printCurrNozPrice(ctx, registerKeeper, priceBefore) + priceAfter, nozPricePercentage, ozoneLimitPercentage = printCurrNozPrice(t, ctx, registerKeeper, priceBefore) dataToExcel = append(dataToExcel, priceAfter) priceBefore = priceAfter } - exportToCSV(dataToExcel) + exportToCSV(t, dataToExcel) } func TestOzPriceChangeAddMultipleResourceNodeAndThenRemove(t *testing.T) { @@ -1516,7 +1515,7 @@ func TestOzPriceChangeAddMultipleResourceNodeAndThenRemove(t *testing.T) { require.Equal(t, stakingtypes.Bonded, validator.Status) require.True(sdk.IntEq(t, valInitialStake, validator.BondedTokens())) _, nozSupply := registerKeeper.NozSupply(ctx) - //nozPriceFactorsSeq0, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(ctx, registerKeeper, NozPriceFactors{ + //nozPriceFactorsSeq0, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(t, ctx, registerKeeper, NozPriceFactors{ // NOzonePrice: registerKeeper.CurrNozPrice(ctx), // InitialTotalStakes: registerKeeper.GetInitialGenesisStakeTotal(ctx), // EffectiveTotalStakes: registerKeeper.GetEffectiveTotalStake(ctx), @@ -1527,7 +1526,7 @@ func TestOzPriceChangeAddMultipleResourceNodeAndThenRemove(t *testing.T) { //}) // start testing - println("********************************* Deliver Create and unsuspend ResourceNode Tx START ********************************************") + t.Log("********************************* Deliver Create and unsuspend ResourceNode Tx START ********************************************") prepayMsg := setupPrepayMsgWithResOwner(resOwners[0]) /********************* deliver tx *********************/ @@ -1543,7 +1542,7 @@ func TestOzPriceChangeAddMultipleResourceNodeAndThenRemove(t *testing.T) { stApp.BeginBlock(abci.RequestBeginBlock{Header: header}) ctx = stApp.BaseApp.NewContext(true, header) - nozPriceFactorsSeq0, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(ctx, registerKeeper, NozPriceFactors{ + nozPriceFactorsSeq0, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(t, ctx, registerKeeper, NozPriceFactors{ NOzonePrice: registerKeeper.CurrNozPrice(ctx), InitialTotalStakes: registerKeeper.GetInitialGenesisStakeTotal(ctx), EffectiveTotalStakes: registerKeeper.GetEffectiveTotalStake(ctx), @@ -1589,10 +1588,10 @@ func TestOzPriceChangeAddMultipleResourceNodeAndThenRemove(t *testing.T) { stApp.BeginBlock(abci.RequestBeginBlock{Header: header}) ctx = stApp.BaseApp.NewContext(true, header) - priceAfter, nozPricePercentage, ozoneLimitPercentage = printCurrNozPrice(ctx, registerKeeper, priceBefore) + priceAfter, nozPricePercentage, ozoneLimitPercentage = printCurrNozPrice(t, ctx, registerKeeper, priceBefore) require.True(t, nozPricePercentage.LT(sdk.ZeroDec()), "noz price should decrease after CreateResourceNode") require.True(t, ozoneLimitPercentage.GT(sdk.ZeroDec()), "OzLimit should increase after CreateResourceNode") - println("********************************* Deliver Create and unsuspend ResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") + t.Log("********************************* Deliver Create and unsuspend ResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") dataToExcel = append(dataToExcel, priceAfter) priceBefore = priceAfter @@ -1627,16 +1626,16 @@ func TestOzPriceChangeAddMultipleResourceNodeAndThenRemove(t *testing.T) { //stApp.BeginBlock(abci.RequestBeginBlock{Header: header}) //ctx = stApp.BaseApp.NewContext(true, header) - priceAfter, nozPricePercentage, ozoneLimitPercentage = printCurrNozPrice(ctx, registerKeeper, priceBefore) + priceAfter, nozPricePercentage, ozoneLimitPercentage = printCurrNozPrice(t, ctx, registerKeeper, priceBefore) require.True(t, nozPricePercentage.GT(sdk.ZeroDec()), "noz price should increase after RemoveResourceNode") require.True(t, ozoneLimitPercentage.LT(sdk.ZeroDec()), "OzLimit should decrease after RemoveResourceNode") - println("********************************* Deliver CreateResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") + t.Log("********************************* Deliver CreateResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") dataToExcel = append(dataToExcel, priceAfter) priceBefore = priceAfter } - exportToCSV(dataToExcel) + exportToCSV(t, dataToExcel) } @@ -1716,7 +1715,7 @@ func TestOzPriceChangeRemoveMultipleResourceNodeAfterGenesis(t *testing.T) { require.Equal(t, stakingtypes.Bonded, validator.Status) require.True(sdk.IntEq(t, valInitialStake, validator.BondedTokens())) _, nozSupply := registerKeeper.NozSupply(ctx) - //nozPriceFactorsSeq0, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(ctx, registerKeeper, NozPriceFactors{ + //nozPriceFactorsSeq0, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(t, ctx, registerKeeper, NozPriceFactors{ // NOzonePrice: registerKeeper.CurrNozPrice(ctx), // InitialTotalStakes: registerKeeper.GetInitialGenesisStakeTotal(ctx), // EffectiveTotalStakes: registerKeeper.GetEffectiveTotalStake(ctx), @@ -1744,7 +1743,7 @@ func TestOzPriceChangeRemoveMultipleResourceNodeAfterGenesis(t *testing.T) { } // start testing - println("********************************* Deliver RemoveResourceNode Tx START ********************************************") + t.Log("********************************* Deliver RemoveResourceNode Tx START ********************************************") prepayMsg := setupPrepayMsgWithResOwner(resOwners[0]) /********************* deliver tx *********************/ @@ -1760,7 +1759,7 @@ func TestOzPriceChangeRemoveMultipleResourceNodeAfterGenesis(t *testing.T) { stApp.BeginBlock(abci.RequestBeginBlock{Header: header}) ctx = stApp.BaseApp.NewContext(true, header) - nozPriceFactorsSeq0, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(ctx, registerKeeper, NozPriceFactors{ + nozPriceFactorsSeq0, nozPricePercentage, ozoneLimitPercentage := printCurrNozPrice(t, ctx, registerKeeper, NozPriceFactors{ NOzonePrice: registerKeeper.CurrNozPrice(ctx), InitialTotalStakes: registerKeeper.GetInitialGenesisStakeTotal(ctx), EffectiveTotalStakes: registerKeeper.GetEffectiveTotalStake(ctx), @@ -1802,25 +1801,25 @@ func TestOzPriceChangeRemoveMultipleResourceNodeAfterGenesis(t *testing.T) { //stApp.BeginBlock(abci.RequestBeginBlock{Header: header}) //ctx = stApp.BaseApp.NewContext(true, header) - priceAfter, nozPricePercentage, ozoneLimitPercentage = printCurrNozPrice(ctx, registerKeeper, priceBefore) + priceAfter, nozPricePercentage, ozoneLimitPercentage = printCurrNozPrice(t, ctx, registerKeeper, priceBefore) require.True(t, nozPricePercentage.GT(sdk.ZeroDec()), "noz price should increase after RemoveResourceNode") require.True(t, ozoneLimitPercentage.LT(sdk.ZeroDec()), "OzLimit should decrease after RemoveResourceNode") - println("********************************* Deliver CreateResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") + t.Log("********************************* Deliver CreateResourceNode Tx END ********************************************\n\n...\n[NEXT TEST CASE]") dataToExcel = append(dataToExcel, priceAfter) priceBefore = priceAfter } - exportToCSV(dataToExcel) + exportToCSV(t, dataToExcel) } -func exportToCSV(factors []NozPriceFactors) { - fmt.Printf("\n%v, %v, %v, %v, %v, %v, %v", "Index", "InitialTotalStake", "TotalUnissuedPrepay", "StakeAndPrepay", +func exportToCSV(t *testing.T, factors []NozPriceFactors) { + t.Logf("\n%v, %v, %v, %v, %v, %v, %v", "Index", "InitialTotalStake", "TotalUnissuedPrepay", "StakeAndPrepay", "NOzonePrice", "RemainingOzoneLimit", "TotalNozSupply") for i, factor := range factors { - fmt.Printf("\n%v, %v, %v, %v, %v, %v, %v", i+1, factor.InitialTotalStakes.String(), factor.TotalUnissuedPrepay.String(), factor.StakeAndPrepay.String(), + t.Logf("\n%v, %v, %v, %v, %v, %v, %v", i+1, factor.InitialTotalStakes.String(), factor.TotalUnissuedPrepay.String(), factor.StakeAndPrepay.String(), factor.NOzonePrice.String(), factor.OzoneLimit.String(), factor.NozSupply.String()) } - println("\n") + t.Log("\n") } From 31fdb8892183d2e5a86c0bb853aa77fadd6f5122 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Dumais Date: Tue, 31 Jan 2023 14:48:49 -0500 Subject: [PATCH 14/17] test/QB-1603 remove push trigger --- .github/workflows/pull-request | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pull-request b/.github/workflows/pull-request index c786e765..9f7c83e0 100644 --- a/.github/workflows/pull-request +++ b/.github/workflows/pull-request @@ -1,6 +1,9 @@ name: Go -on: [pull_request] +on: + pull_request: + types: [opened, reopened, synchronize, ready_for_review] + branches: [main, release, dev] jobs: build: From 28568205a80d4461e3930ba322ad5bca4332ca5c Mon Sep 17 00:00:00 2001 From: BoThe1K <121880388+BoThe1K@users.noreply.github.com> Date: Mon, 13 Feb 2023 15:56:15 +0100 Subject: [PATCH 15/17] QB-1574: update to TM calls, refactor ws (#211) * Add non working version with some modifications * Add init tx return for non evm * Update getTransactionReceipt with tm * Testing ctx for evm api * First rework for http rpc (not fully tested) * Fix with tx decoder * Refactor block and tx to be web3 compatible * QB-1561/evm-update: First version of WS rework (compiled, not fully tested): - fixed issues with wrong block hash generation - removed locks which block rest execution - rework api response strucures for Block, Header - removed tm we connection and replaced with dirrect db access * QB-1561/evm-update: Rework WS client and unified to single api with http conn - add some fixes to event fetcher * Remove not used module * Remove logs * Fix deps * Update txpool module, fix some bugs * Add cosmos type for web3 tx * Comment NewEthTxPayloadVerificationDecorator decorator * Update debug_traceTransaction functionality, fix some bugs * Update coinbase, add versioned db for some rpc endpoints * Fix panic for nil height for evm tx * Fix header * Add async for tests * Add flag for broadcast * Comment for PROD --- .gitignore | 1 + app/ante/eth.go | 35 + app/ante/handler_options.go | 2 + app/app.go | 8 + go.mod | 15 +- go.sum | 24 +- rpc/apis.go | 41 +- rpc/backend/backend.go | 141 ++- rpc/backend/evm_backend.go | 582 +++-------- rpc/backend/utils.go | 97 +- rpc/ethereum/pubsub/pubsub.go | 143 --- rpc/namespaces/ethereum/debug/api.go | 199 ++-- rpc/namespaces/ethereum/eth/api.go | 552 +++++----- rpc/namespaces/ethereum/eth/filters/api.go | 243 +++-- .../ethereum/eth/filters/filter_system.go | 435 +++++--- .../ethereum/eth/filters/filters.go | 15 +- .../ethereum/eth/filters/subscription.go | 3 +- rpc/namespaces/ethereum/miner/api.go | 2 +- rpc/namespaces/ethereum/net/api.go | 42 +- rpc/namespaces/ethereum/txpool/api.go | 62 +- rpc/server.go | 104 ++ rpc/types/block.go | 2 + rpc/types/query_client.go | 7 +- rpc/types/types.go | 92 +- rpc/types/utils.go | 445 ++++++-- rpc/websockets.go | 659 ------------ server/json_rpc.go | 82 +- server/start.go | 42 +- x/evm/client/rest/rest.go | 16 +- x/evm/keeper/state_transition.go | 52 +- x/evm/tracers/js/bigint.go | 20 + x/evm/tracers/js/goja.go | 960 ++++++++++++++++++ .../internal/tracers/4byte_tracer_legacy.js | 86 ++ .../js/internal/tracers/bigram_tracer.js | 47 + .../js/internal/tracers/call_tracer_legacy.js | 252 +++++ .../js/internal/tracers/evmdis_tracer.js | 93 ++ .../js/internal/tracers/noop_tracer_legacy.js | 29 + .../js/internal/tracers/opcount_tracer.js | 32 + .../tracers/prestate_tracer_legacy.js | 115 +++ x/evm/tracers/js/internal/tracers/tracers.go | 59 ++ .../js/internal/tracers/trigram_tracer.js | 49 + .../js/internal/tracers/unigram_tracer.js | 41 + x/evm/tracers/native/4byte.go | 152 +++ x/evm/tracers/native/call.go | 202 ++++ x/evm/tracers/native/noop.go | 78 ++ x/evm/tracers/native/prestate.go | 178 ++++ x/evm/tracers/native/revertreason.go | 108 ++ x/evm/tracers/native/tracer.go | 83 ++ 48 files changed, 4471 insertions(+), 2256 deletions(-) delete mode 100644 rpc/ethereum/pubsub/pubsub.go create mode 100644 rpc/server.go delete mode 100644 rpc/websockets.go create mode 100644 x/evm/tracers/js/bigint.go create mode 100644 x/evm/tracers/js/goja.go create mode 100644 x/evm/tracers/js/internal/tracers/4byte_tracer_legacy.js create mode 100644 x/evm/tracers/js/internal/tracers/bigram_tracer.js create mode 100644 x/evm/tracers/js/internal/tracers/call_tracer_legacy.js create mode 100644 x/evm/tracers/js/internal/tracers/evmdis_tracer.js create mode 100644 x/evm/tracers/js/internal/tracers/noop_tracer_legacy.js create mode 100644 x/evm/tracers/js/internal/tracers/opcount_tracer.js create mode 100644 x/evm/tracers/js/internal/tracers/prestate_tracer_legacy.js create mode 100644 x/evm/tracers/js/internal/tracers/tracers.go create mode 100644 x/evm/tracers/js/internal/tracers/trigram_tracer.js create mode 100644 x/evm/tracers/js/internal/tracers/unigram_tracer.js create mode 100644 x/evm/tracers/native/4byte.go create mode 100644 x/evm/tracers/native/call.go create mode 100644 x/evm/tracers/native/noop.go create mode 100644 x/evm/tracers/native/prestate.go create mode 100644 x/evm/tracers/native/revertreason.go create mode 100644 x/evm/tracers/native/tracer.go diff --git a/.gitignore b/.gitignore index 1f732223..62dfce57 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ vendor/ playground.go /tmp-swagger-gen/ /github.com/ +.DS_Store diff --git a/app/ante/eth.go b/app/ante/eth.go index b354e489..2a9d11b1 100644 --- a/app/ante/eth.go +++ b/app/ante/eth.go @@ -17,6 +17,41 @@ import ( evmtypes "github.com/stratosnet/stratos-chain/x/evm/types" ) +// EthTxPayloadVerificationDecorator validates base tx payload and check some limitations +type EthTxPayloadVerificationDecorator struct { +} + +func NewEthTxPayloadVerificationDecorator() EthTxPayloadVerificationDecorator { + return EthTxPayloadVerificationDecorator{} +} + +// AnteHandle validates msgs count, some signature protection and applied limitations +func (tpvd EthTxPayloadVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { + if len(tx.GetMsgs()) > 1 { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "evm transactions only operates with 1 msg") + } + + for _, msg := range tx.GetMsgs() { + msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx) + if !ok { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil)) + } + + ethTx := msgEthTx.AsTransaction() + // EIP-155 only allowed + if !ethTx.Protected() { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrNotSupported, "legacy pre-eip-155 transactions not supported") + } + + // forbid EIP-2930 update with access list + if len(ethTx.AccessList()) > 0 { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrNotSupported, "eip-2930 transactions not supported") + } + } + + return next(ctx, tx, simulate) +} + // EthSigVerificationDecorator validates an ethereum signatures type EthSigVerificationDecorator struct { evmKeeper EVMKeeper diff --git a/app/ante/handler_options.go b/app/ante/handler_options.go index 2c122484..a55f9589 100644 --- a/app/ante/handler_options.go +++ b/app/ante/handler_options.go @@ -48,6 +48,8 @@ func newEthAnteHandler(options HandlerOptions) sdk.AnteHandler { NewEthSetUpContextDecorator(options.EvmKeeper), // outermost AnteDecorator. SetUpContext must be called first NewEthMempoolFeeDecorator(options.EvmKeeper), // Check eth effective gas price against minimal-gas-prices NewEthValidateBasicDecorator(options.EvmKeeper), + // TODO: UNCOMMENT THIS FOR PROD!!!!!! + // NewEthTxPayloadVerificationDecorator(), NewEthSigVerificationDecorator(options.EvmKeeper), NewEthAccountVerificationDecorator(options.AccountKeeper, options.EvmKeeper), NewEthGasConsumeDecorator(options.EvmKeeper, options.MaxTxGasWanted), diff --git a/app/app.go b/app/app.go index b1ec71b7..3fe367cc 100644 --- a/app/app.go +++ b/app/app.go @@ -192,6 +192,10 @@ var ( } ) +type EVMLKeeperApp interface { + GetEVMKeeper() *evmkeeper.Keeper +} + type NewApp struct { *baseapp.BaseApp @@ -751,6 +755,10 @@ func (app *NewApp) GetPotKeeper() potkeeper.Keeper { return app.potKeeper } +func (app *NewApp) GetEVMKeeper() *evmkeeper.Keeper { + return app.evmKeeper +} + // RegisterSwaggerAPI registers swagger route with API Server func RegisterSwaggerAPI(_ client.Context, rtr *mux.Router) { statikFS, err := fs.New() diff --git a/go.mod b/go.mod index 2d2878b2..9d31e1cb 100644 --- a/go.mod +++ b/go.mod @@ -9,18 +9,17 @@ require ( github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/ibc-go/v3 v3.0.0 github.com/davecgh/go-spew v1.1.1 + github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf github.com/ethereum/go-ethereum v1.10.26 github.com/gogo/protobuf v1.3.3 github.com/golang/protobuf v1.5.2 github.com/gorilla/mux v1.8.0 - github.com/gorilla/websocket v1.5.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/improbable-eng/grpc-web v0.15.0 github.com/ipfs/go-cid v0.1.0 github.com/pkg/errors v0.9.1 github.com/rakyll/statik v0.1.7 github.com/regen-network/cosmos-proto v0.3.1 - github.com/rs/cors v1.8.2 github.com/spf13/cast v1.5.0 github.com/spf13/cobra v1.6.0 github.com/spf13/pflag v1.0.5 @@ -58,6 +57,7 @@ require ( github.com/cosmos/gorocksdb v1.2.0 // indirect github.com/cosmos/iavl v0.19.4 // indirect github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/creachadair/taskgroup v0.3.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/deckarep/golang-set v1.8.0 // indirect @@ -66,10 +66,12 @@ require ( github.com/dgraph-io/badger/v2 v2.2007.2 // indirect github.com/dgraph-io/ristretto v0.0.3 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/edsrzf/mmap-go v1.0.0 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect + github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect github.com/go-kit/kit v0.12.0 // indirect @@ -77,18 +79,22 @@ require ( github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-ole/go-ole v1.2.1 // indirect github.com/go-playground/validator/v10 v10.4.1 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/go-stack/stack v1.8.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/gateway v1.1.0 // indirect + github.com/golang-jwt/jwt/v4 v4.3.0 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.0.0 // indirect github.com/google/orderedcode v0.0.1 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/handlers v1.5.1 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.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-bexpr v0.1.10 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -114,6 +120,7 @@ require ( github.com/minio/highwayhash v1.0.2 // indirect github.com/minio/sha256-simd v1.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/pointerstructure v1.2.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.0.3 // indirect @@ -134,7 +141,9 @@ require ( github.com/prometheus/tsdb v0.7.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rjeczalik/notify v0.9.1 // indirect + github.com/rs/cors v1.8.2 // indirect github.com/rs/zerolog v1.27.0 // indirect + github.com/russross/blackfriday/v2 v2.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/spf13/afero v1.9.2 // indirect @@ -146,6 +155,8 @@ require ( github.com/tidwall/btree v1.5.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect + github.com/urfave/cli/v2 v2.10.2 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect go.etcd.io/bbolt v1.3.6 // indirect diff --git a/go.sum b/go.sum index f3ad16d0..80a95e03 100644 --- a/go.sum +++ b/go.sum @@ -188,7 +188,6 @@ github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 h1:DdzS1m6o/pCqeZ github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8= github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= github.com/cosmos/ledger-cosmos-go v0.12.2/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= -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= @@ -196,6 +195,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM= github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= @@ -224,10 +224,15 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WA github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 h1:Izz0+t1Z5nI16/II7vuEo/nHjodOg0p7+OiDpjX5t1E= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= +github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf h1:Yt+4K30SdjOkRoRRm3vYNQgR+/ZIy0RmeUDZo7Y8zeQ= +github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -256,6 +261,7 @@ github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8S github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= @@ -299,6 +305,8 @@ github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GO github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -315,6 +323,7 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0= github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic= github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= +github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 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= @@ -427,6 +436,7 @@ github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoP github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -523,10 +533,12 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= @@ -582,9 +594,11 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -621,7 +635,6 @@ github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/neilotoole/errgroup v0.1.5/go.mod h1:Q2nLGf+594h0CLBs/Mbg6qOr7GtqDK7C2S41udRnToE= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= @@ -750,7 +763,6 @@ github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubr github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs= github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -858,15 +870,16 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y= +github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo= github.com/vmihailenco/msgpack/v5 v5.1.4/go.mod h1:C5gboKD0TJPqWDTVTtrQNfRbiBwHZGo8UTqP/9/XvLI= github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1281,8 +1294,9 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= diff --git a/rpc/apis.go b/rpc/apis.go index df3a02e4..ca599896 100644 --- a/rpc/apis.go +++ b/rpc/apis.go @@ -5,11 +5,12 @@ package rpc import ( "fmt" - rpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client" + "github.com/tendermint/tendermint/node" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/server" + storetypes "github.com/cosmos/cosmos-sdk/store/types" "github.com/ethereum/go-ethereum/rpc" "github.com/stratosnet/stratos-chain/rpc/backend" @@ -22,6 +23,8 @@ import ( "github.com/stratosnet/stratos-chain/rpc/namespaces/ethereum/txpool" "github.com/stratosnet/stratos-chain/rpc/namespaces/ethereum/web3" "github.com/stratosnet/stratos-chain/rpc/types" + + evmkeeper "github.com/stratosnet/stratos-chain/x/evm/keeper" ) // RPC namespaces and API version @@ -44,16 +47,16 @@ const ( ) // APICreator creates the JSON-RPC API implementations. -type APICreator = func(*server.Context, client.Context, *rpcclient.WSClient) []rpc.API +type APICreator = func(*server.Context, *node.Node, *evmkeeper.Keeper, storetypes.MultiStore, client.Context) []rpc.API // apiCreators defines the JSON-RPC API namespaces. var apiCreators map[string]APICreator func init() { apiCreators = map[string]APICreator{ - EthNamespace: func(ctx *server.Context, clientCtx client.Context, tmWSClient *rpcclient.WSClient) []rpc.API { + EthNamespace: func(ctx *server.Context, tmNode *node.Node, evmKeeper *evmkeeper.Keeper, ms storetypes.MultiStore, clientCtx client.Context) []rpc.API { nonceLock := new(types.AddrLocker) - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx) + evmBackend := backend.NewBackend(ctx, tmNode, evmKeeper, ms, ctx.Logger, clientCtx) return []rpc.API{ { Namespace: EthNamespace, @@ -64,12 +67,12 @@ func init() { { Namespace: EthNamespace, Version: apiVersion, - Service: filters.NewPublicAPI(ctx.Logger, clientCtx, tmWSClient, evmBackend), + Service: filters.NewPublicAPI(ctx.Logger, clientCtx, tmNode.EventBus(), evmBackend), Public: true, }, } }, - Web3Namespace: func(*server.Context, client.Context, *rpcclient.WSClient) []rpc.API { + Web3Namespace: func(*server.Context, *node.Node, *evmkeeper.Keeper, storetypes.MultiStore, client.Context) []rpc.API { return []rpc.API{ { Namespace: Web3Namespace, @@ -79,18 +82,19 @@ func init() { }, } }, - NetNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API { + NetNamespace: func(ctx *server.Context, tmNode *node.Node, evmKeeper *evmkeeper.Keeper, ms storetypes.MultiStore, clientCtx client.Context) []rpc.API { + evmBackend := backend.NewBackend(ctx, tmNode, evmKeeper, ms, ctx.Logger, clientCtx) return []rpc.API{ { Namespace: NetNamespace, Version: apiVersion, - Service: net.NewPublicAPI(clientCtx), + Service: net.NewPublicAPI(evmBackend), Public: true, }, } }, - PersonalNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx) + PersonalNamespace: func(ctx *server.Context, tmNode *node.Node, evmKeeper *evmkeeper.Keeper, ms storetypes.MultiStore, clientCtx client.Context) []rpc.API { + evmBackend := backend.NewBackend(ctx, tmNode, evmKeeper, ms, ctx.Logger, clientCtx) return []rpc.API{ { Namespace: PersonalNamespace, @@ -100,18 +104,19 @@ func init() { }, } }, - TxPoolNamespace: func(ctx *server.Context, _ client.Context, _ *rpcclient.WSClient) []rpc.API { + TxPoolNamespace: func(ctx *server.Context, tmNode *node.Node, evmKeeper *evmkeeper.Keeper, ms storetypes.MultiStore, clientCtx client.Context) []rpc.API { + evmBackend := backend.NewBackend(ctx, tmNode, evmKeeper, ms, ctx.Logger, clientCtx) return []rpc.API{ { Namespace: TxPoolNamespace, Version: apiVersion, - Service: txpool.NewPublicAPI(ctx.Logger), + Service: txpool.NewPublicAPI(ctx.Logger, clientCtx, evmBackend), Public: true, }, } }, - DebugNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx) + DebugNamespace: func(ctx *server.Context, tmNode *node.Node, evmKeeper *evmkeeper.Keeper, ms storetypes.MultiStore, clientCtx client.Context) []rpc.API { + evmBackend := backend.NewBackend(ctx, tmNode, evmKeeper, ms, ctx.Logger, clientCtx) return []rpc.API{ { Namespace: DebugNamespace, @@ -121,8 +126,8 @@ func init() { }, } }, - MinerNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx) + MinerNamespace: func(ctx *server.Context, tmNode *node.Node, evmKeeper *evmkeeper.Keeper, ms storetypes.MultiStore, clientCtx client.Context) []rpc.API { + evmBackend := backend.NewBackend(ctx, tmNode, evmKeeper, ms, ctx.Logger, clientCtx) return []rpc.API{ { Namespace: MinerNamespace, @@ -136,12 +141,12 @@ func init() { } // GetRPCAPIs returns the list of all APIs -func GetRPCAPIs(ctx *server.Context, clientCtx client.Context, tmWSClient *rpcclient.WSClient, selectedAPIs []string) []rpc.API { +func GetRPCAPIs(ctx *server.Context, tmNode *node.Node, evmKeeper *evmkeeper.Keeper, ms storetypes.MultiStore, clientCtx client.Context, selectedAPIs []string) []rpc.API { var apis []rpc.API for _, ns := range selectedAPIs { if creator, ok := apiCreators[ns]; ok { - apis = append(apis, creator(ctx, clientCtx, tmWSClient)...) + apis = append(apis, creator(ctx, tmNode, evmKeeper, ms, clientCtx)...) } else { ctx.Logger.Error("invalid namespace value", "namespace", ns) } diff --git a/rpc/backend/backend.go b/rpc/backend/backend.go index 7b9aee17..1b6080a0 100644 --- a/rpc/backend/backend.go +++ b/rpc/backend/backend.go @@ -2,11 +2,17 @@ package backend import ( "context" + "fmt" "math/big" "time" + cs "github.com/tendermint/tendermint/consensus" "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/mempool" + "github.com/tendermint/tendermint/node" + "github.com/tendermint/tendermint/p2p" tmrpctypes "github.com/tendermint/tendermint/rpc/core/types" + "github.com/tendermint/tendermint/store" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/server" @@ -18,15 +24,20 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" + storetypes "github.com/cosmos/cosmos-sdk/store/types" "github.com/stratosnet/stratos-chain/rpc/types" "github.com/stratosnet/stratos-chain/server/config" + evmkeeper "github.com/stratosnet/stratos-chain/x/evm/keeper" evmtypes "github.com/stratosnet/stratos-chain/x/evm/types" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + tmtypes "github.com/tendermint/tendermint/types" ) // BackendI implements the Cosmos and EVM backend. type BackendI interface { // nolint: revive CosmosBackend EVMBackend + TMBackend } // CosmosBackend implements the functionality shared within cosmos namespaces @@ -37,6 +48,9 @@ type CosmosBackend interface { // GetAccounts() // SignDirect() // SignAmino() + GetEVMKeeper() *evmkeeper.Keeper + GetSdkContext() sdk.Context + GetSdkContextWithHeader(header *tmtypes.Header) (sdk.Context, error) } // EVMBackend implements the functionality shared within ethereum namespaces @@ -47,30 +61,32 @@ type EVMBackend interface { RPCGasCap() uint64 // global gas cap for eth_call over rpc: DoS protection RPCEVMTimeout() time.Duration // global timeout for eth_call over rpc: DoS protection RPCTxFeeCap() float64 // RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for send-transaction variants. The unit is ether. - + RPCFilterCap() int32 RPCMinGasPrice() int64 - SuggestGasTipCap(baseFee *big.Int) (*big.Int, error) + SuggestGasTipCap() (*big.Int, error) + RPCLogsCap() int32 + RPCBlockRangeCap() int32 // Blockchain API BlockNumber() (hexutil.Uint64, error) GetTendermintBlockByNumber(blockNum types.BlockNumber) (*tmrpctypes.ResultBlock, error) GetTendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error) - GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error) - GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) - BlockByNumber(blockNum types.BlockNumber) (*ethtypes.Block, error) - BlockByHash(blockHash common.Hash) (*ethtypes.Block, error) - CurrentHeader() *ethtypes.Header - HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header, error) - HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) + GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (*types.Block, error) + GetBlockByHash(hash common.Hash, fullTx bool) (*types.Block, error) + CurrentHeader() *types.Header + HeaderByNumber(blockNum types.BlockNumber) (*types.Header, error) + HeaderByHash(blockHash common.Hash) (*types.Header, error) PendingTransactions() ([]*sdk.Tx, error) - GetTransactionCount(address common.Address, blockNum types.BlockNumber) (*hexutil.Uint64, error) + GetTransactionCount(address common.Address, blockNum types.BlockNumber) (hexutil.Uint64, error) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, error) GetCoinbase() (sdk.AccAddress, error) - GetTransactionByHash(txHash common.Hash) (*types.RPCTransaction, error) - GetTxByEthHash(txHash common.Hash) (*tmrpctypes.ResultTx, error) + GetTransactionByHash(txHash common.Hash) (*types.Transaction, error) + GetTxByHash(txHash common.Hash) (*tmrpctypes.ResultTx, error) GetTxByTxIndex(height int64, txIndex uint) (*tmrpctypes.ResultTx, error) EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *types.BlockNumber) (hexutil.Uint64, error) - BaseFee(height int64) (*big.Int, error) + BaseFee() (*big.Int, error) + GetLogsByNumber(blockNum types.BlockNumber) ([][]*ethtypes.Log, error) + BlockBloom(height *int64) (ethtypes.Bloom, error) // Fee API FeeHistory(blockCount rpc.DecimalOrHex, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*types.FeeHistoryResult, error) @@ -81,32 +97,107 @@ type EVMBackend interface { GetLogsByHeight(height *int64) ([][]*ethtypes.Log, error) ChainConfig() *params.ChainConfig SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.TransactionArgs, error) - GetEthereumMsgsFromTendermintBlock(block *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) []*evmtypes.MsgEthereumTx +} + +type TMBackend interface { + // tendermint helpers + GetNode() *node.Node + GetBlockStore() *store.BlockStore + GetMempool() mempool.Mempool + GetConsensusReactor() *cs.Reactor + GetSwitch() *p2p.Switch } var _ BackendI = (*Backend)(nil) // Backend implements the BackendI interface type Backend struct { - ctx context.Context - clientCtx client.Context - queryClient *types.QueryClient // gRPC query client - logger log.Logger - cfg config.Config + ctx context.Context + clientCtx client.Context + tmNode *node.Node // directly tendermint access, new impl + evmkeeper *evmkeeper.Keeper + ms storetypes.MultiStore + logger log.Logger + cfg config.Config } // NewBackend creates a new Backend instance for cosmos and ethereum namespaces -func NewBackend(ctx *server.Context, logger log.Logger, clientCtx client.Context) *Backend { +func NewBackend(ctx *server.Context, tmNode *node.Node, evmkeeper *evmkeeper.Keeper, ms storetypes.MultiStore, logger log.Logger, clientCtx client.Context) *Backend { appConf, err := config.GetConfig(ctx.Viper) if err != nil { panic(err) } return &Backend{ - ctx: context.Background(), - clientCtx: clientCtx, - queryClient: types.NewQueryClient(clientCtx), - logger: logger.With("module", "backend"), - cfg: appConf, + ctx: context.Background(), + clientCtx: clientCtx, + tmNode: tmNode, + evmkeeper: evmkeeper, + ms: ms, + logger: logger.With("module", "backend"), + cfg: appConf, + } +} + +func (b *Backend) GetEVMKeeper() *evmkeeper.Keeper { + return b.evmkeeper +} + +func (b *Backend) copySdkContext(ms storetypes.MultiStore, header *tmtypes.Header) sdk.Context { + sdkCtx := sdk.NewContext(ms, tmproto.Header{}, true, b.logger) + if header != nil { + return sdkCtx.WithHeaderHash( + header.Hash(), + ).WithBlockHeader( + types.FormatTmHeaderToProto(header), + ).WithBlockHeight( + header.Height, + ).WithProposer( + sdk.ConsAddress(header.ProposerAddress), + ) + } + return sdkCtx +} + +func (b *Backend) GetSdkContext() sdk.Context { + return b.copySdkContext(b.ms.CacheMultiStore(), nil) +} + +func (b *Backend) GetSdkContextWithHeader(header *tmtypes.Header) (sdk.Context, error) { + if header == nil { + return b.GetSdkContext(), nil + } + latestHeight := b.GetBlockStore().Height() + if latestHeight == 0 { + return sdk.Context{}, fmt.Errorf("block store not loaded") } + if latestHeight == header.Height { + return b.copySdkContext(b.ms.CacheMultiStore(), header), nil + } + + cms, err := b.ms.CacheMultiStoreWithVersion(header.Height) + if err != nil { + return sdk.Context{}, err + } + return b.copySdkContext(cms, header), nil +} + +func (b *Backend) GetNode() *node.Node { + return b.tmNode +} + +func (b *Backend) GetBlockStore() *store.BlockStore { + return b.tmNode.BlockStore() +} + +func (b *Backend) GetMempool() mempool.Mempool { + return b.tmNode.Mempool() +} + +func (b *Backend) GetConsensusReactor() *cs.Reactor { + return b.tmNode.ConsensusReactor() +} + +func (b *Backend) GetSwitch() *p2p.Switch { + return b.tmNode.Switch() } diff --git a/rpc/backend/evm_backend.go b/rpc/backend/evm_backend.go index 98e0c611..978284e4 100644 --- a/rpc/backend/evm_backend.go +++ b/rpc/backend/evm_backend.go @@ -1,16 +1,12 @@ package backend import ( - "bytes" "encoding/json" "fmt" "math/big" - "strconv" "time" "github.com/pkg/errors" - "google.golang.org/grpc" - "google.golang.org/grpc/metadata" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" @@ -20,46 +16,36 @@ import ( "github.com/ethereum/go-ethereum/rpc" tmrpctypes "github.com/tendermint/tendermint/rpc/core/types" - tmtypes "github.com/tendermint/tendermint/types" + tmjsonrpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" "github.com/cosmos/cosmos-sdk/client/flags" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - grpctypes "github.com/cosmos/cosmos-sdk/types/grpc" "github.com/stratosnet/stratos-chain/rpc/types" stratos "github.com/stratosnet/stratos-chain/types" evmtypes "github.com/stratosnet/stratos-chain/x/evm/types" + tmrpccore "github.com/tendermint/tendermint/rpc/core" ) -var bAttributeKeyEthereumBloom = []byte(evmtypes.AttributeKeyEthereumBloom) - // BlockNumber returns the current block number in abci app state. // Because abci app state could lag behind from tendermint latest block, it's more stable // for the client to use the latest block number in abci app state than tendermint rpc. func (b *Backend) BlockNumber() (hexutil.Uint64, error) { - // do any grpc query, ignore the response and use the returned block height - var header metadata.MD - _, err := b.queryClient.Params(b.ctx, &evmtypes.QueryParamsRequest{}, grpc.Header(&header)) + res, err := tmrpccore.Block(nil, nil) if err != nil { return hexutil.Uint64(0), err } - blockHeightHeader := header.Get(grpctypes.GRPCBlockHeightHeader) - if headerLen := len(blockHeightHeader); headerLen != 1 { - return 0, fmt.Errorf("unexpected '%s' gRPC header length; got %d, expected: %d", grpctypes.GRPCBlockHeightHeader, headerLen, 1) - } - - height, err := strconv.ParseUint(blockHeightHeader[0], 10, 64) - if err != nil { - return 0, fmt.Errorf("failed to parse block height: %w", err) + if res.Block == nil { + return hexutil.Uint64(0), errors.Errorf("block store not loaded") } - return hexutil.Uint64(height), nil + return hexutil.Uint64(res.Block.Height), nil } // GetBlockByNumber returns the block identified by number. -func (b *Backend) GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error) { +func (b *Backend) GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (*types.Block, error) { resBlock, err := b.GetTendermintBlockByNumber(blockNum) if err != nil { return nil, err @@ -70,119 +56,63 @@ func (b *Backend) GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map return nil, nil } - res, err := b.EthBlockFromTendermint(resBlock.Block, fullTx) + res, err := types.EthBlockFromTendermint(b.clientCtx.TxConfig.TxDecoder(), resBlock.Block, fullTx) if err != nil { b.logger.Debug("EthBlockFromTendermint failed", "height", blockNum, "error", err.Error()) - return nil, err + return nil, nil } - return res, nil -} - -// GetBlockByHash returns the block identified by hash. -func (b *Backend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) { - resBlock, err := b.clientCtx.Client.BlockByHash(b.ctx, hash.Bytes()) + // override dynamicly miner address + sdkCtx, err := b.GetSdkContextWithHeader(&resBlock.Block.Header) if err != nil { - b.logger.Debug("BlockByHash block not found", "hash", hash.Hex(), "error", err.Error()) + b.logger.Debug("GetSdkContextWithHeader context", "height", blockNum, "error", err.Error()) return nil, err } - if resBlock == nil || resBlock.Block == nil { - b.logger.Debug("BlockByHash block not found", "hash", hash.Hex()) - return nil, nil - } - - return b.EthBlockFromTendermint(resBlock.Block, fullTx) -} - -// BlockByNumber returns the block identified by number. -func (b *Backend) BlockByNumber(blockNum types.BlockNumber) (*ethtypes.Block, error) { - height := blockNum.Int64() - - switch blockNum { - case types.EthLatestBlockNumber: - currentBlockNumber, _ := b.BlockNumber() - if currentBlockNumber > 0 { - height = int64(currentBlockNumber) - } - case types.EthPendingBlockNumber: - currentBlockNumber, _ := b.BlockNumber() - if currentBlockNumber > 0 { - height = int64(currentBlockNumber) - } - case types.EthEarliestBlockNumber: - height = 1 - default: - if blockNum < 0 { - return nil, errors.Errorf("incorrect block height: %d", height) - } - } - - resBlock, err := b.clientCtx.Client.Block(b.ctx, &height) + validator, err := b.evmkeeper.GetCoinbaseAddress(sdkCtx) if err != nil { - b.logger.Debug("HeaderByNumber failed", "height", height) + b.logger.Debug("GetCoinbaseAddress no validator", "height", blockNum, "error", err.Error()) return nil, err } + res.Miner = validator - if resBlock == nil || resBlock.Block == nil { - return nil, errors.Errorf("block not found for height %d", height) - } - - return b.EthBlockFromTm(resBlock.Block) + return res, nil } -// BlockByHash returns the block identified by hash. -func (b *Backend) BlockByHash(hash common.Hash) (*ethtypes.Block, error) { - resBlock, err := b.clientCtx.Client.BlockByHash(b.ctx, hash.Bytes()) +// GetBlockByHash returns the block identified by hash. +func (b *Backend) GetBlockByHash(hash common.Hash, fullTx bool) (*types.Block, error) { + resBlock, err := tmrpccore.BlockByHash(nil, hash.Bytes()) if err != nil { - b.logger.Debug("HeaderByHash failed", "hash", hash.Hex()) + b.logger.Debug("BlockByHash block not found", "hash", hash.Hex(), "error", err.Error()) return nil, err } if resBlock == nil || resBlock.Block == nil { - return nil, errors.Errorf("block not found for hash %s", hash) + b.logger.Debug("BlockByHash block not found", "hash", hash.Hex()) + return nil, nil } - return b.EthBlockFromTm(resBlock.Block) -} - -func (b *Backend) EthBlockFromTm(block *tmtypes.Block) (*ethtypes.Block, error) { - height := block.Height - bloom, err := b.BlockBloom(&height) + res, err := types.EthBlockFromTendermint(b.clientCtx.TxConfig.TxDecoder(), resBlock.Block, fullTx) if err != nil { - b.logger.Debug("HeaderByNumber BlockBloom failed", "height", height) + b.logger.Debug("EthBlockFromTendermint failed", "hash", hash.Hex(), "error", err.Error()) + return nil, nil } - baseFee, err := b.BaseFee(height) + // override dynamicly miner address + sdkCtx, err := b.GetSdkContextWithHeader(&resBlock.Block.Header) if err != nil { - b.logger.Debug("HeaderByNumber BaseFee failed", "height", height, "error", err.Error()) + b.logger.Debug("GetSdkContextWithHeader context", "hash", hash.Hex(), "error", err.Error()) return nil, err } - ethHeader := types.EthHeaderFromTendermint(block.Header, bloom, baseFee) - - var txs []*ethtypes.Transaction - for _, txBz := range block.Txs { - tx, err := b.clientCtx.TxConfig.TxDecoder()(txBz) - if err != nil { - b.logger.Debug("failed to decode transaction in block", "height", height, "error", err.Error()) - continue - } - - for _, msg := range tx.GetMsgs() { - ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) - if !ok { - continue - } - - tx := ethMsg.AsTransaction() - txs = append(txs, tx) - } + validator, err := b.evmkeeper.GetCoinbaseAddress(sdkCtx) + if err != nil { + b.logger.Debug("GetCoinbaseAddress no validator", "hash", hash.Hex(), "error", err.Error()) + return nil, err } + res.Miner = validator - // TODO: add tx receipts - ethBlock := ethtypes.NewBlock(ethHeader, txs, nil, nil, nil) - return ethBlock, nil + return res, nil } // GetTendermintBlockByNumber returns a Tendermint format block by block number @@ -210,9 +140,9 @@ func (b *Backend) GetTendermintBlockByNumber(blockNum types.BlockNumber) (*tmrpc } } - resBlock, err := b.clientCtx.Client.Block(b.ctx, &height) + resBlock, err := tmrpccore.Block(nil, &height) if err != nil { - if resBlock, err = b.clientCtx.Client.Block(b.ctx, nil); err != nil { + if resBlock, err = tmrpccore.Block(nil, nil); err != nil { b.logger.Debug("tendermint client failed to get latest block", "height", height, "error", err.Error()) return nil, nil } @@ -228,7 +158,7 @@ func (b *Backend) GetTendermintBlockByNumber(blockNum types.BlockNumber) (*tmrpc // GetTendermintBlockByHash returns a Tendermint format block by block number func (b *Backend) GetTendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error) { - resBlock, err := b.clientCtx.Client.BlockByHash(b.ctx, blockHash.Bytes()) + resBlock, err := tmrpccore.BlockByHash(nil, blockHash.Bytes()) if err != nil { b.logger.Debug("tendermint client failed to get block", "blockHash", blockHash.Hex(), "error", err.Error()) } @@ -243,148 +173,21 @@ func (b *Backend) GetTendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.R // BlockBloom query block bloom filter from block results func (b *Backend) BlockBloom(height *int64) (ethtypes.Bloom, error) { - result, err := b.clientCtx.Client.BlockResults(b.ctx, height) + result, err := tmrpccore.BlockResults(nil, height) if err != nil { return ethtypes.Bloom{}, err } - for _, event := range result.EndBlockEvents { - if event.Type != evmtypes.EventTypeBlockBloom { - continue - } - - for _, attr := range event.Attributes { - if bytes.Equal(attr.Key, bAttributeKeyEthereumBloom) { - return ethtypes.BytesToBloom(attr.Value), nil - } - } - } - return ethtypes.Bloom{}, errors.New("block bloom event is not found") -} - -// EthBlockFromTendermint returns a JSON-RPC compatible Ethereum block from a given Tendermint block and its block result. -func (b *Backend) EthBlockFromTendermint( - block *tmtypes.Block, - fullTx bool, -) (map[string]interface{}, error) { - ethRPCTxs := []interface{}{} - - ctx := types.ContextWithHeight(block.Height) - - baseFee, err := b.BaseFee(block.Height) - if err != nil { - return nil, err - } - - resBlockResult, err := b.clientCtx.Client.BlockResults(ctx, &block.Height) - if err != nil { - return nil, err - } - - txResults := resBlockResult.TxsResults - txIndex := uint64(0) - - for i, txBz := range block.Txs { - tx, err := b.clientCtx.TxConfig.TxDecoder()(txBz) - if err != nil { - b.logger.Debug("failed to decode transaction in block", "height", block.Height, "error", err.Error()) - continue - } - - for _, msg := range tx.GetMsgs() { - ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) - if !ok { - continue - } - - tx := ethMsg.AsTransaction() - - // check tx exists on EVM by cross checking with blockResults - if txResults[i].Code != 0 { - b.logger.Debug("invalid tx result code", "hash", tx.Hash().Hex()) - continue - } - - if !fullTx { - hash := tx.Hash() - ethRPCTxs = append(ethRPCTxs, hash) - continue - } - - rpcTx, err := types.NewRPCTransaction( - tx, - common.BytesToHash(block.Hash()), - uint64(block.Height), - txIndex, - baseFee, - ) - if err != nil { - b.logger.Debug("NewTransactionFromData for receipt failed", "hash", tx.Hash().Hex(), "error", err.Error()) - continue - } - ethRPCTxs = append(ethRPCTxs, rpcTx) - txIndex++ - } - } - - bloom, err := b.BlockBloom(&block.Height) - if err != nil { - b.logger.Debug("failed to query BlockBloom", "height", block.Height, "error", err.Error()) - } - - req := &evmtypes.QueryValidatorAccountRequest{ - ConsAddress: sdk.ConsAddress(block.Header.ProposerAddress).String(), - } - - res, err := b.queryClient.ValidatorAccount(ctx, req) - if err != nil { - b.logger.Debug( - "failed to query validator operator address", - "height", block.Height, - "cons-address", req.ConsAddress, - "error", err.Error(), - ) - return nil, err - } - - addr, err := sdk.AccAddressFromBech32(res.AccountAddress) - if err != nil { - return nil, err - } - - validatorAddr := common.BytesToAddress(addr) - - gasLimit, err := types.BlockMaxGasFromConsensusParams(ctx, b.clientCtx, block.Height) - if err != nil { - b.logger.Error("failed to query consensus params", "error", err.Error()) - } - - gasUsed := uint64(0) - - for _, txsResult := range txResults { - // workaround for cosmos-sdk bug. https://github.com/cosmos/cosmos-sdk/issues/10832 - if txsResult.GetCode() == 11 && txsResult.GetLog() == "no block gas left to run tx: out of gas" { - // block gas limit has exceeded, other txs must have failed with same reason. - break - } - gasUsed += uint64(txsResult.GetGasUsed()) - } - - formattedBlock := types.FormatBlock( - block.Header, block.Size(), - gasLimit, new(big.Int).SetUint64(gasUsed), - ethRPCTxs, bloom, validatorAddr, baseFee, - ) - return formattedBlock, nil + return types.GetBlockBloom(result) } // CurrentHeader returns the latest block header -func (b *Backend) CurrentHeader() *ethtypes.Header { +func (b *Backend) CurrentHeader() *types.Header { header, _ := b.HeaderByNumber(types.EthLatestBlockNumber) return header } // HeaderByNumber returns the block header identified by height. -func (b *Backend) HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header, error) { +func (b *Backend) HeaderByNumber(blockNum types.BlockNumber) (*types.Header, error) { height := blockNum.Int64() switch blockNum { @@ -406,30 +209,37 @@ func (b *Backend) HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header, } } - resBlock, err := b.clientCtx.Client.Block(b.ctx, &height) + resBlock, err := tmrpccore.Block(nil, &height) if err != nil { b.logger.Debug("HeaderByNumber failed") return nil, err } - bloom, err := b.BlockBloom(&resBlock.Block.Height) + ethHeader, err := types.EthHeaderFromTendermint(resBlock.Block.Header) if err != nil { - b.logger.Debug("HeaderByNumber BlockBloom failed", "height", resBlock.Block.Height) + b.logger.Debug("HeaderByNumber EthHeaderFromTendermint failed", "height", resBlock.Block.Height, "error", err.Error()) + return nil, err } - baseFee, err := b.BaseFee(resBlock.Block.Height) + // override dynamicly miner address + sdkCtx, err := b.GetSdkContextWithHeader(&resBlock.Block.Header) if err != nil { - b.logger.Debug("HeaderByNumber BaseFee failed", "height", resBlock.Block.Height, "error", err.Error()) + b.logger.Debug("GetSdkContextWithHeader context", "height", blockNum, "error", err.Error()) return nil, err } - ethHeader := types.EthHeaderFromTendermint(resBlock.Block.Header, bloom, baseFee) + validator, err := b.evmkeeper.GetCoinbaseAddress(sdkCtx) + if err != nil { + b.logger.Debug("EthBlockFromTendermint no validator", "height", blockNum, "error", err.Error()) + return nil, err + } + ethHeader.Coinbase = validator return ethHeader, nil } // HeaderByHash returns the block header identified by hash. -func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) { - resBlock, err := b.clientCtx.Client.BlockByHash(b.ctx, blockHash.Bytes()) +func (b *Backend) HeaderByHash(blockHash common.Hash) (*types.Header, error) { + resBlock, err := tmrpccore.BlockByHash(nil, blockHash.Bytes()) if err != nil { b.logger.Debug("HeaderByHash failed", "hash", blockHash.Hex()) return nil, err @@ -439,31 +249,35 @@ func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) return nil, errors.Errorf("block not found for hash %s", blockHash.Hex()) } - bloom, err := b.BlockBloom(&resBlock.Block.Height) + ethHeader, err := types.EthHeaderFromTendermint(resBlock.Block.Header) if err != nil { - b.logger.Debug("HeaderByHash BlockBloom failed", "height", resBlock.Block.Height) + b.logger.Debug("HeaderByHash EthHeaderFromTendermint failed", "height", resBlock.Block.Height, "error", err.Error()) + return nil, err } - baseFee, err := b.BaseFee(resBlock.Block.Height) + // override dynamicly miner address + sdkCtx, err := b.GetSdkContextWithHeader(&resBlock.Block.Header) if err != nil { - b.logger.Debug("HeaderByHash BaseFee failed", "height", resBlock.Block.Height, "error", err.Error()) + b.logger.Debug("GetSdkContextWithHeader context", "hash", blockHash.Hex(), "error", err.Error()) return nil, err } - ethHeader := types.EthHeaderFromTendermint(resBlock.Block.Header, bloom, baseFee) + validator, err := b.evmkeeper.GetCoinbaseAddress(sdkCtx) + if err != nil { + b.logger.Debug("EthBlockFromTendermint no validator", "hash", blockHash.Hex(), "error", err.Error()) + return nil, err + } + ethHeader.Coinbase = validator return ethHeader, nil } // PendingTransactions returns the transactions that are in the transaction pool // and have a from address that is one of the accounts this node manages. func (b *Backend) PendingTransactions() ([]*sdk.Tx, error) { - res, err := b.clientCtx.Client.UnconfirmedTxs(b.ctx, nil) - if err != nil { - return nil, err - } + txs := b.GetMempool().ReapMaxTxs(100) - result := make([]*sdk.Tx, 0, len(res.Txs)) - for _, txBz := range res.Txs { + result := make([]*sdk.Tx, 0, len(txs)) + for _, txBz := range txs { tx, err := b.clientCtx.TxConfig.TxDecoder()(txBz) if err != nil { return nil, err @@ -477,7 +291,7 @@ func (b *Backend) PendingTransactions() ([]*sdk.Tx, error) { // GetLogsByHeight returns all the logs from all the ethereum transactions in a block. func (b *Backend) GetLogsByHeight(height *int64) ([][]*ethtypes.Log, error) { // NOTE: we query the state in case the tx result logs are not persisted after an upgrade. - blockRes, err := b.clientCtx.Client.BlockResults(b.ctx, height) + blockRes, err := tmrpccore.BlockResults(nil, height) if err != nil { return nil, err } @@ -497,7 +311,7 @@ func (b *Backend) GetLogsByHeight(height *int64) ([][]*ethtypes.Log, error) { // GetLogs returns all the logs from all the ethereum transactions in a block. func (b *Backend) GetLogs(hash common.Hash) ([][]*ethtypes.Log, error) { - block, err := b.clientCtx.Client.BlockByHash(b.ctx, hash.Bytes()) + block, err := tmrpccore.BlockByHash(nil, hash.Bytes()) if err != nil { return nil, err } @@ -537,12 +351,7 @@ func (b *Backend) BloomStatus() (uint64, uint64) { // GetCoinbase is the address that staking rewards will be send to (alias for Etherbase). func (b *Backend) GetCoinbase() (sdk.AccAddress, error) { - node, err := b.clientCtx.GetNode() - if err != nil { - return nil, err - } - - status, err := node.Status(b.ctx) + status, err := tmrpccore.Status(nil) if err != nil { return nil, err } @@ -551,7 +360,8 @@ func (b *Backend) GetCoinbase() (sdk.AccAddress, error) { ConsAddress: sdk.ConsAddress(status.ValidatorInfo.Address).String(), } - res, err := b.queryClient.ValidatorAccount(b.ctx, req) + ctx := b.GetSdkContext() + res, err := b.GetEVMKeeper().ValidatorAccount(sdk.WrapSDKContext(ctx), req) if err != nil { return nil, err } @@ -561,115 +371,51 @@ func (b *Backend) GetCoinbase() (sdk.AccAddress, error) { } // GetTransactionByHash returns the Ethereum format transaction identified by Ethereum transaction hash -func (b *Backend) GetTransactionByHash(txHash common.Hash) (*types.RPCTransaction, error) { - res, err := b.GetTxByEthHash(txHash) - hexTx := txHash.Hex() +func (b *Backend) GetTransactionByHash(txHash common.Hash) (*types.Transaction, error) { + res, err := b.GetTxByHash(txHash) if err != nil { - // try to find tx in mempool - txs, err := b.PendingTransactions() + // TODO: Get chain id value from genesis + tx, err := types.GetPendingTx(b.clientCtx.TxConfig.TxDecoder(), b.GetMempool(), txHash) if err != nil { - b.logger.Debug("tx not found", "hash", hexTx, "error", err.Error()) + b.logger.Debug("tx not found", "hash", txHash, "error", err.Error()) return nil, nil } - - for _, tx := range txs { - msg, err := evmtypes.UnwrapEthereumMsg(tx, txHash) - if err != nil { - // not ethereum tx - continue - } - - if msg.Hash == hexTx { - rpctx, err := types.NewTransactionFromMsg( - msg, - common.Hash{}, - uint64(0), - uint64(0), - b.ChainConfig().ChainID, - ) - if err != nil { - return nil, err - } - return rpctx, nil - } - } - - b.logger.Debug("tx not found", "hash", hexTx) - return nil, nil - } - - if res.TxResult.Code != 0 { - return nil, errors.New("invalid ethereum tx") - } - - msgIndex, attrs := types.FindTxAttributes(res.TxResult.Events, hexTx) - if msgIndex < 0 { - return nil, fmt.Errorf("ethereum tx not found in msgs: %s", hexTx) + return tx, nil } - tx, err := b.clientCtx.TxConfig.TxDecoder()(res.Tx) - if err != nil { + block := b.GetBlockStore().LoadBlock(res.Height) + if block == nil { + b.logger.Debug("eth_getTransactionByHash", "hash", txHash, "block not found") return nil, err } - // the `msgIndex` is inferred from tx events, should be within the bound. - msg, ok := tx.GetMsgs()[msgIndex].(*evmtypes.MsgEthereumTx) - if !ok { - return nil, errors.New("invalid ethereum tx") - } - - block, err := b.clientCtx.Client.Block(b.ctx, &res.Height) - if err != nil { - b.logger.Debug("block not found", "height", res.Height, "error", err.Error()) - return nil, err - } + blockHash := common.BytesToHash(block.Hash()) + blockHeight := uint64(res.Height) + txIndex := uint64(res.Index) - // Try to find txIndex from events - found := false - txIndex, err := types.GetUint64Attribute(attrs, evmtypes.AttributeKeyTxIndex) - if err == nil { - found = true - } else { - // Fallback to find tx index by iterating all valid eth transactions - blockRes, err := b.clientCtx.Client.BlockResults(b.ctx, &block.Block.Height) - if err != nil { - return nil, nil - } - msgs := b.GetEthereumMsgsFromTendermintBlock(block, blockRes) - for i := range msgs { - if msgs[i].Hash == hexTx { - txIndex = uint64(i) - found = true - break - } - } - } - if !found { - return nil, errors.New("can't find index of ethereum tx") - } - - return types.NewTransactionFromMsg( - msg, - common.BytesToHash(block.BlockID.Hash.Bytes()), - uint64(res.Height), - txIndex, - b.ChainConfig().ChainID, + return types.TmTxToEthTx( + b.clientCtx.TxConfig.TxDecoder(), + res.Tx, + &blockHash, + &blockHeight, + &txIndex, ) } -// GetTxByEthHash uses `/tx_query` to find transaction by ethereum tx hash -// TODO: Don't need to convert once hashing is fixed on Tendermint -// https://github.com/tendermint/tendermint/issues/6539 -func (b *Backend) GetTxByEthHash(hash common.Hash) (*tmrpctypes.ResultTx, error) { - query := fmt.Sprintf("%s.%s='%s'", evmtypes.TypeMsgEthereumTx, evmtypes.AttributeKeyEthereumTxHash, hash.Hex()) - resTxs, err := b.clientCtx.Client.TxSearch(b.ctx, query, false, nil, nil, "") +func (b *Backend) GetTxByHash(hash common.Hash) (*tmrpctypes.ResultTx, error) { + resTx, err := tmrpccore.Tx(nil, hash.Bytes(), false) if err != nil { - return nil, err - } - if len(resTxs.Txs) == 0 { - return nil, errors.Errorf("ethereum tx not found for hash %s", hash.Hex()) + query := fmt.Sprintf("%s.%s='%s'", evmtypes.TypeMsgEthereumTx, evmtypes.AttributeKeyEthereumTxHash, hash.Hex()) + resTxs, err := tmrpccore.TxSearch(new(tmjsonrpctypes.Context), query, false, nil, nil, "") + if err != nil { + return nil, err + } + if len(resTxs.Txs) == 0 { + return nil, errors.Errorf("ethereum tx not found for hash %s", hash.Hex()) + } + return resTxs.Txs[0], nil } - return resTxs.Txs[0], nil + return resTx, nil } // GetTxByTxIndex uses `/tx_query` to find transaction by tx index of valid ethereum txs @@ -678,7 +424,7 @@ func (b *Backend) GetTxByTxIndex(height int64, index uint) (*tmrpctypes.ResultTx height, evmtypes.TypeMsgEthereumTx, evmtypes.AttributeKeyTxIndex, index, ) - resTxs, err := b.clientCtx.Client.TxSearch(b.ctx, query, false, nil, nil, "") + resTxs, err := tmrpccore.TxSearch(new(tmjsonrpctypes.Context), query, false, nil, nil, "") if err != nil { return nil, err } @@ -722,7 +468,8 @@ func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, e } // Query params to use the EVM denomination - res, err := b.queryClient.QueryClient.Params(b.ctx, &evmtypes.QueryParamsRequest{}) + sdkCtx := b.GetSdkContext() + res, err := b.GetEVMKeeper().Params(sdk.WrapSDKContext(sdkCtx), &evmtypes.QueryParamsRequest{}) if err != nil { b.logger.Error("failed to query evm params", "error", err.Error()) return common.Hash{}, err @@ -743,7 +490,13 @@ func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, e return common.Hash{}, err } - txHash := msg.AsTransaction().Hash() + ethTx := msg.AsTransaction() + if !ethTx.Protected() { + // Ensure only eip155 signed transactions are submitted. + return common.Hash{}, errors.New("legacy pre-eip-155 transactions not supported") + } + + txHash := ethTx.Hash() // Broadcast transaction in sync mode (default) // NOTE: If error is encountered on the node, the broadcast will not return an error @@ -778,10 +531,23 @@ func (b *Backend) EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *ty GasCap: b.RPCGasCap(), } - // From ContextWithHeight: if the provided height is 0, - // it will return an empty context and the gRPC query will use + resBlock, err := b.GetTendermintBlockByNumber(blockNr) + if err != nil { + return 0, err + } + + // return if requested block height is greater than the current one or chain not synced + if resBlock == nil || resBlock.Block == nil { + return 0, nil + } + + // it will return an empty context and the sdk.Context will use // the latest block height for querying. - res, err := b.queryClient.EstimateGas(types.ContextWithHeight(blockNr.Int64()), &req) + sdkCtx, err := b.GetSdkContextWithHeader(&resBlock.Block.Header) + if err != nil { + return 0, err + } + res, err := b.GetEVMKeeper().EstimateGas(sdk.WrapSDKContext(sdkCtx), &req) if err != nil { return 0, err } @@ -789,26 +555,21 @@ func (b *Backend) EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *ty } // GetTransactionCount returns the number of transactions at the given address up to the given block number. -func (b *Backend) GetTransactionCount(address common.Address, blockNum types.BlockNumber) (*hexutil.Uint64, error) { +func (b *Backend) GetTransactionCount(address common.Address, blockNum types.BlockNumber) (hexutil.Uint64, error) { // Get nonce (sequence) from account from := sdk.AccAddress(address.Bytes()) accRet := b.clientCtx.AccountRetriever err := accRet.EnsureExists(b.clientCtx, from) if err != nil { - // account doesn't exist yet, return 0 - n := hexutil.Uint64(0) - return &n, nil + return hexutil.Uint64(0), nil } - includePending := blockNum == types.EthPendingBlockNumber - nonce, err := b.getAccountNonce(address, includePending, blockNum.Int64(), b.logger) + nonce, err := b.getAccountNonce(address, blockNum) if err != nil { - return nil, err + return hexutil.Uint64(0), err } - - n := hexutil.Uint64(nonce) - return &n, nil + return hexutil.Uint64(nonce), nil } // RPCGasCap is the global gas cap for eth-call variants. @@ -850,7 +611,8 @@ func (b *Backend) RPCBlockRangeCap() int32 { // the node config. If set value is 0, it will default to 20. func (b *Backend) RPCMinGasPrice() int64 { - evmParams, err := b.queryClient.Params(b.ctx, &evmtypes.QueryParamsRequest{}) + sdkCtx := b.GetSdkContext() + evmParams, err := b.GetEVMKeeper().Params(sdk.WrapSDKContext(sdkCtx), &evmtypes.QueryParamsRequest{}) if err != nil { return stratos.DefaultGasPrice } @@ -866,7 +628,8 @@ func (b *Backend) RPCMinGasPrice() int64 { // ChainConfig returns the latest ethereum chain configuration func (b *Backend) ChainConfig() *params.ChainConfig { - params, err := b.queryClient.Params(b.ctx, &evmtypes.QueryParamsRequest{}) + sdkCtx := b.GetSdkContext() + params, err := b.GetEVMKeeper().Params(sdk.WrapSDKContext(sdkCtx), &evmtypes.QueryParamsRequest{}) if err != nil { return nil } @@ -877,13 +640,15 @@ func (b *Backend) ChainConfig() *params.ChainConfig { // SuggestGasTipCap returns the suggested tip cap // Although we don't support tx prioritization yet, but we return a positive value to help client to // mitigate the base fee changes. -func (b *Backend) SuggestGasTipCap(baseFee *big.Int) (*big.Int, error) { - if baseFee == nil { +func (b *Backend) SuggestGasTipCap() (*big.Int, error) { + baseFee, err := b.BaseFee() + if err != nil { // london hardfork not enabled or feemarket not enabled return big.NewInt(0), nil } - params, err := b.queryClient.Params(b.ctx, &evmtypes.QueryParamsRequest{}) + sdkCtx := b.GetSdkContext() + params, err := b.GetEVMKeeper().Params(sdk.WrapSDKContext(sdkCtx), &evmtypes.QueryParamsRequest{}) if err != nil { return nil, err } @@ -909,9 +674,23 @@ func (b *Backend) SuggestGasTipCap(baseFee *big.Int) (*big.Int, error) { // If the base fee is not enabled globally, the query returns nil. // If the London hard fork is not activated at the current height, the query will // return nil. -func (b *Backend) BaseFee(height int64) (*big.Int, error) { +func (b *Backend) BaseFee() (*big.Int, error) { + resBlock, err := b.GetTendermintBlockByNumber(types.EthLatestBlockNumber) + if err != nil { + return nil, err + } + + // return if requested block height is greater than the current one or chain not synced + if resBlock == nil || resBlock.Block == nil { + return nil, nil + } + + sdkCtx, err := b.GetSdkContextWithHeader(&resBlock.Block.Header) + if err != nil { + return nil, err + } // return BaseFee if London hard fork is activated and feemarket is enabled - res, err := b.queryClient.BaseFee(types.ContextWithHeight(height), &evmtypes.QueryBaseFeeRequest{}) + res, err := b.GetEVMKeeper().BaseFee(sdk.WrapSDKContext(sdkCtx), nil) if err != nil { return nil, err } @@ -980,14 +759,14 @@ func (b *Backend) FeeHistory( } // tendermint block result - tendermintBlockResult, err := b.clientCtx.Client.BlockResults(b.ctx, &tendermintblock.Block.Height) + tendermintBlockResult, err := tmrpccore.BlockResults(nil, &tendermintblock.Block.Height) if tendermintBlockResult == nil { b.logger.Debug("block result not found", "height", tendermintblock.Block.Height, "error", err.Error()) return nil, err } oneFeeHistory := types.OneFeeHistory{} - err = b.processBlock(tendermintblock, ðBlock, rewardPercentiles, tendermintBlockResult, &oneFeeHistory) + err = b.processBlock(tendermintblock, ethBlock, rewardPercentiles, tendermintBlockResult, &oneFeeHistory) if err != nil { return nil, err } @@ -1017,36 +796,3 @@ func (b *Backend) FeeHistory( return &feeHistory, nil } - -// GetEthereumMsgsFromTendermintBlock returns all real MsgEthereumTxs from a Tendermint block. -// It also ensures consistency over the correct txs indexes across RPC endpoints -func (b *Backend) GetEthereumMsgsFromTendermintBlock(block *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) []*evmtypes.MsgEthereumTx { - var result []*evmtypes.MsgEthereumTx - - txResults := blockRes.TxsResults - - for i, tx := range block.Block.Txs { - // check tx exists on EVM by cross checking with blockResults - if txResults[i].Code != 0 { - b.logger.Debug("invalid tx result code", "cosmos-hash", hexutil.Encode(tx.Hash())) - continue - } - - tx, err := b.clientCtx.TxConfig.TxDecoder()(tx) - if err != nil { - b.logger.Debug("failed to decode transaction in block", "height", block.Block.Height, "error", err.Error()) - continue - } - - for _, msg := range tx.GetMsgs() { - ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) - if !ok { - continue - } - - result = append(result, ethMsg) - } - } - - return result -} diff --git a/rpc/backend/utils.go b/rpc/backend/utils.go index b2ac112c..81bc8d28 100644 --- a/rpc/backend/utils.go +++ b/rpc/backend/utils.go @@ -8,16 +8,14 @@ import ( "math/big" "sort" - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ethtypes "github.com/ethereum/go-ethereum/core/types" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/libs/log" tmrpctypes "github.com/tendermint/tendermint/rpc/core/types" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stratosnet/stratos-chain/rpc/types" evmtypes "github.com/stratosnet/stratos-chain/x/evm/types" ) @@ -50,13 +48,18 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac return args, errors.New("latest header is nil") } + baseFee, err := b.BaseFee() + if err != nil { + return args, err + } + // If user specifies both maxPriorityfee and maxFee, then we do not // need to consult the chain for defaults. It's definitely a London tx. if args.MaxPriorityFeePerGas == nil || args.MaxFeePerGas == nil { // In this clause, user left some fields unspecified. - if head.BaseFee != nil && args.GasPrice == nil { + if baseFee != nil && args.GasPrice == nil { if args.MaxPriorityFeePerGas == nil { - tip, err := b.SuggestGasTipCap(head.BaseFee) + tip, err := b.SuggestGasTipCap() if err != nil { return args, err } @@ -66,7 +69,7 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac if args.MaxFeePerGas == nil { gasFeeCap := new(big.Int).Add( (*big.Int)(args.MaxPriorityFeePerGas), - new(big.Int).Mul(head.BaseFee, big.NewInt(2)), + new(big.Int).Mul(baseFee, big.NewInt(2)), ) args.MaxFeePerGas = (*hexutil.Big)(gasFeeCap) } @@ -81,15 +84,15 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac } if args.GasPrice == nil { - price, err := b.SuggestGasTipCap(head.BaseFee) + price, err := b.SuggestGasTipCap() if err != nil { return args, err } - if head.BaseFee != nil { + if baseFee != nil { // The legacy tx gas price suggestion should not add 2x base fee // because all fees are consumed, so it would result in a spiral // upwards. - price.Add(price, head.BaseFee) + price.Add(price, baseFee) } args.GasPrice = (*hexutil.Big)(price) } @@ -107,7 +110,10 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac if args.Nonce == nil { // get the nonce from the account retriever // ignore error in case tge account doesn't exist yet - nonce, _ := b.getAccountNonce(*args.From, true, 0, b.logger) + nonce, err := b.getAccountNonce(*args.From, types.EthPendingBlockNumber) + if err != nil { + return args, err + } args.Nonce = (*hexutil.Uint64)(&nonce) } @@ -170,64 +176,47 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac // If the pending value is true, it will iterate over the mempool (pending) // txs in order to compute and return the pending tx sequence. // Todo: include the ability to specify a blockNumber -func (b *Backend) getAccountNonce(accAddr common.Address, pending bool, height int64, logger log.Logger) (uint64, error) { - queryClient := authtypes.NewQueryClient(b.clientCtx) - res, err := queryClient.Account(types.ContextWithHeight(height), &authtypes.QueryAccountRequest{Address: sdk.AccAddress(accAddr.Bytes()).String()}) - if err != nil { - return 0, err +func (b *Backend) getAccountNonce(address common.Address, height types.BlockNumber) (uint64, error) { + var ( + pendingNonce uint64 + ) + if height == types.EthPendingBlockNumber { + pendingNonce = types.GetPendingTxCountByAddress(b.clientCtx.TxConfig.TxDecoder(), b.GetMempool(), address) } - var acc authtypes.AccountI - if err := b.clientCtx.InterfaceRegistry.UnpackAny(res.Account, &acc); err != nil { - return 0, err + req := evmtypes.QueryCosmosAccountRequest{ + Address: address.Hex(), } - nonce := acc.GetSequence() + block, err := b.GetTendermintBlockByNumber(height) + if err != nil { + return 0, err + } - if !pending { - return nonce, nil + if block.Block == nil { + return 0, fmt.Errorf("failed to get block for %d height", height) } - // the account retriever doesn't include the uncommitted transactions on the nonce so we need to - // to manually add them. - pendingTxs, err := b.PendingTransactions() + sdkCtx, err := b.GetSdkContextWithHeader(&block.Block.Header) if err != nil { - logger.Error("failed to fetch pending transactions", "error", err.Error()) - return nonce, nil + return 0, err } - - // add the uncommitted txs to the nonce counter - // only supports `MsgEthereumTx` style tx - for _, tx := range pendingTxs { - for _, msg := range (*tx).GetMsgs() { - ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) - if !ok { - // not ethereum tx - break - } - - sender, err := ethMsg.GetSender(b.ChainConfig().ChainID) - if err != nil { - continue - } - if sender == accAddr { - nonce++ - } - } + acc, err := b.GetEVMKeeper().CosmosAccount(sdk.WrapSDKContext(sdkCtx), &req) + if err != nil { + return pendingNonce, err } - - return nonce, nil + return acc.GetSequence() + pendingNonce, nil } // output: targetOneFeeHistory func (b *Backend) processBlock( tendermintBlock *tmrpctypes.ResultBlock, - ethBlock *map[string]interface{}, + ethBlock *types.Block, rewardPercentiles []float64, tendermintBlockResult *tmrpctypes.ResultBlockResults, targetOneFeeHistory *types.OneFeeHistory, ) error { blockHeight := tendermintBlock.Block.Height - blockBaseFee, err := b.BaseFee(blockHeight) + blockBaseFee, err := b.BaseFee() if err != nil { return err } @@ -236,15 +225,9 @@ func (b *Backend) processBlock( targetOneFeeHistory.BaseFee = blockBaseFee // set gas used ratio - gasLimitUint64, ok := (*ethBlock)["gasLimit"].(hexutil.Uint64) - if !ok { - return fmt.Errorf("invalid gas limit type: %T", (*ethBlock)["gasLimit"]) - } + gasLimitUint64 := hexutil.Uint64(ethBlock.GasLimit.ToInt().Uint64()) - gasUsedBig, ok := (*ethBlock)["gasUsed"].(*hexutil.Big) - if !ok { - return fmt.Errorf("invalid gas used type: %T", (*ethBlock)["gasUsed"]) - } + gasUsedBig := ethBlock.GasUsed gasusedfloat, _ := new(big.Float).SetInt(gasUsedBig.ToInt()).Float64() diff --git a/rpc/ethereum/pubsub/pubsub.go b/rpc/ethereum/pubsub/pubsub.go deleted file mode 100644 index 4ac7f34c..00000000 --- a/rpc/ethereum/pubsub/pubsub.go +++ /dev/null @@ -1,143 +0,0 @@ -package pubsub - -import ( - "sync" - "sync/atomic" - - "github.com/pkg/errors" - - coretypes "github.com/tendermint/tendermint/rpc/core/types" -) - -type UnsubscribeFunc func() - -type EventBus interface { - AddTopic(name string, src <-chan coretypes.ResultEvent) error - RemoveTopic(name string) - Subscribe(name string) (<-chan coretypes.ResultEvent, UnsubscribeFunc, error) - Topics() []string -} - -type memEventBus struct { - topics map[string]<-chan coretypes.ResultEvent - topicsMux *sync.RWMutex - subscribers map[string]map[uint64]chan<- coretypes.ResultEvent - subscribersMux *sync.RWMutex - currentUniqueID uint64 -} - -func NewEventBus() EventBus { - return &memEventBus{ - topics: make(map[string]<-chan coretypes.ResultEvent), - topicsMux: new(sync.RWMutex), - subscribers: make(map[string]map[uint64]chan<- coretypes.ResultEvent), - subscribersMux: new(sync.RWMutex), - } -} - -func (m *memEventBus) GenUniqueID() uint64 { - return atomic.AddUint64(&m.currentUniqueID, 1) -} - -func (m *memEventBus) Topics() (topics []string) { - m.topicsMux.RLock() - defer m.topicsMux.RUnlock() - - topics = make([]string, 0, len(m.topics)) - for topicName := range m.topics { - topics = append(topics, topicName) - } - - return topics -} - -func (m *memEventBus) AddTopic(name string, src <-chan coretypes.ResultEvent) error { - m.topicsMux.RLock() - _, ok := m.topics[name] - m.topicsMux.RUnlock() - - if ok { - return errors.New("topic already registered") - } - - m.topicsMux.Lock() - m.topics[name] = src - m.topicsMux.Unlock() - - go m.publishTopic(name, src) - - return nil -} - -func (m *memEventBus) RemoveTopic(name string) { - m.topicsMux.Lock() - delete(m.topics, name) - m.topicsMux.Unlock() -} - -func (m *memEventBus) Subscribe(name string) (<-chan coretypes.ResultEvent, UnsubscribeFunc, error) { - m.topicsMux.RLock() - _, ok := m.topics[name] - m.topicsMux.RUnlock() - - if !ok { - return nil, nil, errors.Errorf("topic not found: %s", name) - } - - ch := make(chan coretypes.ResultEvent) - m.subscribersMux.Lock() - defer m.subscribersMux.Unlock() - - id := m.GenUniqueID() - if _, ok := m.subscribers[name]; !ok { - m.subscribers[name] = make(map[uint64]chan<- coretypes.ResultEvent) - } - m.subscribers[name][id] = ch - - unsubscribe := func() { - m.subscribersMux.Lock() - defer m.subscribersMux.Unlock() - delete(m.subscribers[name], id) - } - - return ch, unsubscribe, nil -} - -func (m *memEventBus) publishTopic(name string, src <-chan coretypes.ResultEvent) { - for { - msg, ok := <-src - if !ok { - m.closeAllSubscribers(name) - m.topicsMux.Lock() - delete(m.topics, name) - m.topicsMux.Unlock() - return - } - m.publishAllSubscribers(name, msg) - } -} - -func (m *memEventBus) closeAllSubscribers(name string) { - m.subscribersMux.Lock() - defer m.subscribersMux.Unlock() - - subsribers := m.subscribers[name] - delete(m.subscribers, name) - - for _, sub := range subsribers { - close(sub) - } -} - -func (m *memEventBus) publishAllSubscribers(name string, msg coretypes.ResultEvent) { - m.subscribersMux.RLock() - subsribers := m.subscribers[name] - m.subscribersMux.RUnlock() - - for _, sub := range subsribers { - select { - case sub <- msg: - default: - } - } -} diff --git a/rpc/namespaces/ethereum/debug/api.go b/rpc/namespaces/ethereum/debug/api.go index 363f12ab..93c4908d 100644 --- a/rpc/namespaces/ethereum/debug/api.go +++ b/rpc/namespaces/ethereum/debug/api.go @@ -2,10 +2,12 @@ package debug import ( "bytes" + "context" "encoding/json" "errors" "fmt" "io" + "math/big" "os" "runtime" "runtime/debug" @@ -14,14 +16,19 @@ import ( "time" "github.com/davecgh/go-spew/spew" + "github.com/ethereum/go-ethereum/eth/tracers" stderrors "github.com/pkg/errors" + "github.com/ethereum/go-ethereum/eth/tracers/logger" + "github.com/tendermint/tendermint/libs/log" tmrpctypes "github.com/tendermint/tendermint/rpc/core/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/server" + ethtypes "github.com/ethereum/go-ethereum/core/types" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus/ethash" @@ -29,9 +36,33 @@ import ( "github.com/stratosnet/stratos-chain/rpc/backend" rpctypes "github.com/stratosnet/stratos-chain/rpc/types" + jstracers "github.com/stratosnet/stratos-chain/x/evm/tracers/js" + nativetracers "github.com/stratosnet/stratos-chain/x/evm/tracers/native" evmtypes "github.com/stratosnet/stratos-chain/x/evm/types" + tmrpccore "github.com/tendermint/tendermint/rpc/core" +) + +const ( + // defaultTraceTimeout is the amount of time a single transaction can execute + // by default before being forcefully aborted. + defaultTraceTimeout = 5 * time.Second + + // NOTE: Commented for now. Maybe even not needed as cosmos could obtain state by version + // If we have transaction, we could just take snapshot from previous height, whih should be enough + // defaultTraceReexec is the number of blocks the tracer is willing to go back + // and reexecute to produce missing historical state necessary to run a specific + // trace. + // defaultTraceReexec = uint64(128) ) +// initialize tracers +// NOTE: Required action as some go-ethereum modules incapsulated, so some tracer copy pasted +// so should be periodically checked in order to update/extend functionality +func init() { + jstracers.InitTracer() + nativetracers.InitTracer() +} + // HandlerT keeps track of the cpu profiler and trace execution type HandlerT struct { cpuFilename string @@ -43,133 +74,125 @@ type HandlerT struct { // API is the collection of tracing APIs exposed over the private debugging endpoint. type API struct { - ctx *server.Context - logger log.Logger - backend backend.EVMBackend - clientCtx client.Context - queryClient *rpctypes.QueryClient - handler *HandlerT + ctx *server.Context + logger log.Logger + backend backend.BackendI + clientCtx client.Context + handler *HandlerT } // NewAPI creates a new API definition for the tracing methods of the Ethereum service. func NewAPI( ctx *server.Context, - backend backend.EVMBackend, + backend backend.BackendI, clientCtx client.Context, ) *API { return &API{ - ctx: ctx, - logger: ctx.Logger.With("module", "debug"), - backend: backend, - clientCtx: clientCtx, - queryClient: rpctypes.NewQueryClient(clientCtx), - handler: new(HandlerT), + ctx: ctx, + logger: ctx.Logger.With("module", "debug"), + backend: backend, + clientCtx: clientCtx, + handler: new(HandlerT), } } // TraceTransaction returns the structured logs created during the execution of EVM // and returns them as a JSON object. -func (a *API) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfig) (interface{}, error) { +func (a *API) TraceTransaction(ctx context.Context, hash common.Hash, config *tracers.TraceConfig) (interface{}, error) { + // Assemble the structured logger or the JavaScript tracer + var ( + tracer tracers.Tracer + err error + timeout = defaultTraceTimeout + ) a.logger.Debug("debug_traceTransaction", "hash", hash) + // Get transaction by hash - transaction, err := a.backend.GetTxByEthHash(hash) + resultTx, err := a.backend.GetTxByHash(hash) if err != nil { - a.logger.Debug("tx not found", "hash", hash) + a.logger.Debug("debug_traceTransaction", "tx not found", "hash", hash) return nil, err } - // check if block number is 0 - if transaction.Height == 0 { - return nil, errors.New("genesis is not traceable") - } - - blk, err := a.backend.GetTendermintBlockByNumber(rpctypes.BlockNumber(transaction.Height)) + tx, err := a.clientCtx.TxConfig.TxDecoder()(resultTx.Tx) if err != nil { - a.logger.Debug("block not found", "height", transaction.Height) + a.logger.Debug("tx not found", "hash", hash) return nil, err } - msgIndex, _ := rpctypes.FindTxAttributes(transaction.TxResult.Events, hash.Hex()) - if msgIndex < 0 { - return nil, fmt.Errorf("ethereum tx not found in msgs: %s", hash.Hex()) + if len(tx.GetMsgs()) == 0 { + return nil, fmt.Errorf("empty msg") } - // check tx index is not out of bound - if uint32(len(blk.Block.Txs)) < transaction.Index { - a.logger.Debug("tx index out of bounds", "index", transaction.Index, "hash", hash.String(), "height", blk.Block.Height) - return nil, fmt.Errorf("transaction not included in block %v", blk.Block.Height) + ethMsg, ok := tx.GetMsgs()[0].(*evmtypes.MsgEthereumTx) + if !ok { + a.logger.Debug("debug_traceTransaction", "invalid transaction type", "type", fmt.Sprintf("%T", tx)) + return logger.NewStructLogger(nil).GetResult() } - var predecessors []*evmtypes.MsgEthereumTx - for _, txBz := range blk.Block.Txs[:transaction.Index] { - tx, err := a.clientCtx.TxConfig.TxDecoder()(txBz) - if err != nil { - a.logger.Debug("failed to decode transaction in block", "height", blk.Block.Height, "error", err.Error()) - continue - } - for _, msg := range tx.GetMsgs() { - ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) - if !ok { - continue - } - - predecessors = append(predecessors, ethMsg) - } + parentHeight := resultTx.Height - 1 + parentBlock, err := tmrpccore.Block(nil, &parentHeight) + if err != nil || parentBlock.Block == nil { + a.logger.Debug("debug_traceTransaction", "block not found", "height", resultTx.Height) + return nil, err } - - tx, err := a.clientCtx.TxConfig.TxDecoder()(transaction.Tx) - if err != nil { - a.logger.Debug("tx not found", "hash", hash) + currentBlock, err := tmrpccore.Block(nil, &resultTx.Height) + if err != nil || parentBlock.Block == nil { + a.logger.Debug("debug_traceTransaction", "block not found", "height", resultTx.Height) return nil, err } - // add predecessor messages in current cosmos tx - for i := 0; i < msgIndex; i++ { - ethMsg, ok := tx.GetMsgs()[i].(*evmtypes.MsgEthereumTx) - if !ok { - continue - } - predecessors = append(predecessors, ethMsg) + txctx := &tracers.Context{ + BlockHash: common.BytesToHash(currentBlock.Block.Hash()), + TxIndex: int(resultTx.Index), + TxHash: ethMsg.AsTransaction().Hash(), } - ethMessage, ok := tx.GetMsgs()[msgIndex].(*evmtypes.MsgEthereumTx) - if !ok { - a.logger.Debug("invalid transaction type", "type", fmt.Sprintf("%T", tx)) - return nil, fmt.Errorf("invalid transaction type %T", tx) + // Default tracer is the struct logger + tracer = logger.NewStructLogger(config.Config) + if config.Tracer != nil { + tracer, err = tracers.New(*config.Tracer, txctx, config.TracerConfig) + if err != nil { + return nil, err + } } - - traceTxRequest := evmtypes.QueryTraceTxRequest{ - Msg: ethMessage, - Predecessors: predecessors, - BlockNumber: blk.Block.Height, - BlockTime: blk.Block.Time, - BlockHash: common.Bytes2Hex(blk.BlockID.Hash), + // Define a meaningful timeout of a single transaction trace + if config.Timeout != nil { + if timeout, err = time.ParseDuration(*config.Timeout); err != nil { + return nil, err + } } - if config != nil { - traceTxRequest.TraceConfig = config - } + deadlineCtx, cancel := context.WithTimeout(ctx, timeout) + go func() { + <-deadlineCtx.Done() + if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) { + tracer.Stop(errors.New("execution timeout")) + } + }() + defer cancel() - // minus one to get the context of block beginning - contextHeight := transaction.Height - 1 - if contextHeight < 1 { - // 0 is a special value in `ContextWithHeight` - contextHeight = 1 + sdkCtx, err := a.backend.GetSdkContextWithHeader(&parentBlock.Block.Header) + if err != nil { + return nil, fmt.Errorf("Failed to load state at height: %d\n", parentHeight) } - traceResult, err := a.queryClient.TraceTx(rpctypes.ContextWithHeight(contextHeight), &traceTxRequest) + + keeper := a.backend.GetEVMKeeper() + + cfg, err := keeper.EVMConfig(sdkCtx) if err != nil { return nil, err } + signer := ethtypes.MakeSigner(cfg.ChainConfig, big.NewInt(parentBlock.Block.Height)) - // Response format is unknown due to custom tracer config param - // More information can be found here https://geth.ethereum.org/docs/dapp/tracing-filtered - var decodedResult interface{} - err = json.Unmarshal(traceResult.Data, &decodedResult) + msg, err := ethMsg.AsMessage(signer, cfg.BaseFee) if err != nil { return nil, err } - - return decodedResult, nil + if _, err := keeper.ApplyMessage(sdkCtx, msg, tracer, false); err != nil { + return nil, fmt.Errorf("tracing failed: %w", err) + } + return tracer.GetResult() } // TraceBlockByNumber returns the structured logs created during the execution of @@ -246,7 +269,6 @@ func (a *API) traceBlock(height rpctypes.BlockNumber, config *evmtypes.TraceConf // 0 is a special value for `ContextWithHeight`. contextHeight = 1 } - ctxWithHeight := rpctypes.ContextWithHeight(int64(contextHeight)) traceBlockRequest := &evmtypes.QueryTraceBlockRequest{ Txs: txsMessages, @@ -256,7 +278,12 @@ func (a *API) traceBlock(height rpctypes.BlockNumber, config *evmtypes.TraceConf BlockHash: common.Bytes2Hex(block.BlockID.Hash), } - res, err := a.queryClient.TraceBlock(ctxWithHeight, traceBlockRequest) + sdkCtx, err := a.backend.GetSdkContextWithHeader(&block.Block.Header) + if err != nil { + return nil, err + } + + res, err := a.backend.GetEVMKeeper().TraceBlock(sdk.WrapSDKContext(sdkCtx), traceBlockRequest) if err != nil { return nil, err } @@ -465,7 +492,7 @@ func (a *API) GetHeaderRlp(number uint64) (hexutil.Bytes, error) { // GetBlockRlp retrieves the RLP encoded for of a single block. func (a *API) GetBlockRlp(number uint64) (hexutil.Bytes, error) { - block, err := a.backend.BlockByNumber(rpctypes.BlockNumber(number)) + block, err := a.backend.GetBlockByNumber(rpctypes.BlockNumber(number), true) if err != nil { return nil, err } @@ -475,7 +502,7 @@ func (a *API) GetBlockRlp(number uint64) (hexutil.Bytes, error) { // PrintBlock retrieves a block and returns its pretty printed form. func (a *API) PrintBlock(number uint64) (string, error) { - block, err := a.backend.BlockByNumber(rpctypes.BlockNumber(number)) + block, err := a.backend.GetBlockByNumber(rpctypes.BlockNumber(number), true) if err != nil { return "", err } diff --git a/rpc/namespaces/ethereum/eth/api.go b/rpc/namespaces/ethereum/eth/api.go index 44b315f4..05243e5e 100644 --- a/rpc/namespaces/ethereum/eth/api.go +++ b/rpc/namespaces/ethereum/eth/api.go @@ -7,6 +7,7 @@ import ( "math" "math/big" + abci "github.com/tendermint/tendermint/abci/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -20,7 +21,6 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/ethereum/go-ethereum/accounts/keystore" @@ -35,19 +35,21 @@ import ( "github.com/stratosnet/stratos-chain/crypto/hd" "github.com/stratosnet/stratos-chain/ethereum/eip712" "github.com/stratosnet/stratos-chain/rpc/backend" + "github.com/stratosnet/stratos-chain/rpc/types" rpctypes "github.com/stratosnet/stratos-chain/rpc/types" stratos "github.com/stratosnet/stratos-chain/types" evmtypes "github.com/stratosnet/stratos-chain/x/evm/types" + mempl "github.com/tendermint/tendermint/mempool" + tmrpccore "github.com/tendermint/tendermint/rpc/core" ) // PublicAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec. type PublicAPI struct { ctx context.Context clientCtx client.Context - queryClient *rpctypes.QueryClient chainIDEpoch *big.Int logger log.Logger - backend backend.EVMBackend + backend backend.BackendI nonceLock *rpctypes.AddrLocker signer ethtypes.Signer } @@ -56,7 +58,7 @@ type PublicAPI struct { func NewPublicAPI( logger log.Logger, clientCtx client.Context, - backend backend.EVMBackend, + backend backend.BackendI, nonceLock *rpctypes.AddrLocker, ) *PublicAPI { algos, _ := clientCtx.Keyring.SupportedAlgorithms() @@ -88,7 +90,6 @@ func NewPublicAPI( api := &PublicAPI{ ctx: context.Background(), clientCtx: clientCtx, - queryClient: rpctypes.NewQueryClient(clientCtx), chainIDEpoch: cfg.ChainID, logger: logger.With("client", "json-rpc"), backend: backend, @@ -104,10 +105,6 @@ func (e *PublicAPI) ClientCtx() client.Context { return e.clientCtx } -func (e *PublicAPI) QueryClient() *rpctypes.QueryClient { - return e.queryClient -} - func (e *PublicAPI) Ctx() context.Context { return e.ctx } @@ -121,18 +118,9 @@ func (e *PublicAPI) ProtocolVersion() hexutil.Uint { // ChainId is the EIP-155 replay-protection chain id for the current ethereum chain config. func (e *PublicAPI) ChainId() (*hexutil.Big, error) { // nolint e.logger.Debug("eth_chainId") - // if current block is at or past the EIP-155 replay-protection fork block, return chainID from config - bn, err := e.backend.BlockNumber() - if err != nil { - e.logger.Debug("failed to fetch latest block number", "error", err.Error()) - return (*hexutil.Big)(e.chainIDEpoch), nil - } - - if config := e.backend.ChainConfig(); config.IsEIP155(new(big.Int).SetUint64(uint64(bn))) { - return (*hexutil.Big)(config.ChainID), nil - } - - return nil, fmt.Errorf("chain not synced beyond EIP-155 replay-protection fork block") + ctx := e.backend.GetSdkContext() + params := e.backend.GetEVMKeeper().GetParams(ctx) + return (*hexutil.Big)(params.ChainConfig.ChainID.BigInt()), nil } // Syncing returns false in case the node is currently not syncing with the network. It can be up to date or has not @@ -145,7 +133,11 @@ func (e *PublicAPI) ChainId() (*hexutil.Big, error) { // nolint func (e *PublicAPI) Syncing() (interface{}, error) { e.logger.Debug("eth_syncing") - status, err := e.clientCtx.Client.Status(e.ctx) + if !e.backend.GetConsensusReactor().WaitSync() { + return false, nil + } + + status, err := tmrpccore.Status(nil) if err != nil { return false, err } @@ -157,9 +149,9 @@ func (e *PublicAPI) Syncing() (interface{}, error) { return map[string]interface{}{ "startingBlock": hexutil.Uint64(status.SyncInfo.EarliestBlockHeight), "currentBlock": hexutil.Uint64(status.SyncInfo.LatestBlockHeight), - // "highestBlock": nil, // NA - // "pulledStates": nil, // NA - // "knownStates": nil, // NA + "highestBlock": nil, // NA + "pulledStates": nil, // NA + "knownStates": nil, // NA }, nil } @@ -194,12 +186,16 @@ func (e *PublicAPI) GasPrice() (*hexutil.Big, error) { result *big.Int err error ) - if head := e.backend.CurrentHeader(); head.BaseFee != nil { - result, err = e.backend.SuggestGasTipCap(head.BaseFee) + baseFee, err := e.backend.BaseFee() + if err != nil { + return nil, err + } + if baseFee != nil { + result, err = e.backend.SuggestGasTipCap() if err != nil { return nil, err } - result = result.Add(result, head.BaseFee) + result = result.Add(result, baseFee) } else { result = big.NewInt(e.backend.RPCMinGasPrice()) } @@ -210,8 +206,7 @@ func (e *PublicAPI) GasPrice() (*hexutil.Big, error) { // MaxPriorityFeePerGas returns a suggestion for a gas tip cap for dynamic fee transactions. func (e *PublicAPI) MaxPriorityFeePerGas() (*hexutil.Big, error) { e.logger.Debug("eth_maxPriorityFeePerGas") - head := e.backend.CurrentHeader() - tipcap, err := e.backend.SuggestGasTipCap(head.BaseFee) + tipcap, err := e.backend.SuggestGasTipCap() if err != nil { return nil, err } @@ -257,21 +252,23 @@ func (e *PublicAPI) GetBalance(address common.Address, blockNrOrHash rpctypes.Bl return nil, err } - req := &evmtypes.QueryBalanceRequest{ - Address: address.String(), - } - - res, err := e.queryClient.Balance(rpctypes.ContextWithHeight(blockNum.Int64()), req) + resBlock, err := e.backend.GetTendermintBlockByNumber(blockNum) if err != nil { return nil, err } - val, ok := sdk.NewIntFromString(res.Balance) - if !ok { - return nil, errors.New("invalid balance") + // return if requested block height is greater than the current one or chain not synced + if resBlock == nil || resBlock.Block == nil { + return nil, nil + } + + sdkCtx, err := e.backend.GetSdkContextWithHeader(&resBlock.Block.Header) + if err != nil { + return nil, err } + balance := e.backend.GetEVMKeeper().GetBalance(sdkCtx, address) - return (*hexutil.Big)(val.BigInt()), nil + return (*hexutil.Big)(balance), nil } // GetStorageAt returns the contract storage at the given address, block number, and key. @@ -283,26 +280,30 @@ func (e *PublicAPI) GetStorageAt(address common.Address, key string, blockNrOrHa return nil, err } - req := &evmtypes.QueryStorageRequest{ - Address: address.String(), - Key: key, + resBlock, err := e.backend.GetTendermintBlockByNumber(blockNum) + if err != nil { + return nil, err + } + + // return if requested block height is greater than the current one or chain not synced + if resBlock == nil || resBlock.Block == nil { + return nil, nil } - res, err := e.queryClient.Storage(rpctypes.ContextWithHeight(blockNum.Int64()), req) + sdkCtx, err := e.backend.GetSdkContextWithHeader(&resBlock.Block.Header) if err != nil { return nil, err } - - value := common.HexToHash(res.Value) - return value.Bytes(), nil + state := e.backend.GetEVMKeeper().GetState(sdkCtx, address, common.HexToHash(key)) + return state.Bytes(), nil } // GetTransactionCount returns the number of transactions at the given address up to the given block number. -func (e *PublicAPI) GetTransactionCount(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (*hexutil.Uint64, error) { +func (e *PublicAPI) GetTransactionCount(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (hexutil.Uint64, error) { e.logger.Debug("eth_getTransactionCount", "address", address.Hex(), "block number or hash", blockNrOrHash) blockNum, err := e.getBlockNumber(blockNrOrHash) if err != nil { - return nil, err + return 0, err } return e.backend.GetTransactionCount(address, blockNum) } @@ -311,7 +312,7 @@ func (e *PublicAPI) GetTransactionCount(address common.Address, blockNrOrHash rp func (e *PublicAPI) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint { e.logger.Debug("eth_getBlockTransactionCountByHash", "hash", hash.Hex()) - block, err := e.clientCtx.Client.BlockByHash(e.ctx, hash.Bytes()) + block, err := tmrpccore.BlockByHash(nil, hash.Bytes()) if err != nil { e.logger.Debug("block not found", "hash", hash.Hex(), "error", err.Error()) return nil @@ -322,20 +323,14 @@ func (e *PublicAPI) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Ui return nil } - blockRes, err := e.clientCtx.Client.BlockResults(e.ctx, &block.Block.Height) - if err != nil { - return nil - } - - ethMsgs := e.backend.GetEthereumMsgsFromTendermintBlock(block, blockRes) - n := hexutil.Uint(len(ethMsgs)) + n := hexutil.Uint(len(block.Block.Txs)) return &n } // GetBlockTransactionCountByNumber returns the number of transactions in the block identified by number. func (e *PublicAPI) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint { e.logger.Debug("eth_getBlockTransactionCountByNumber", "height", blockNum.Int64()) - block, err := e.clientCtx.Client.Block(e.ctx, blockNum.TmHeight()) + block, err := tmrpccore.Block(nil, blockNum.TmHeight()) if err != nil { e.logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error()) return nil @@ -346,13 +341,7 @@ func (e *PublicAPI) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumb return nil } - blockRes, err := e.clientCtx.Client.BlockResults(e.ctx, &block.Block.Height) - if err != nil { - return nil - } - - ethMsgs := e.backend.GetEthereumMsgsFromTendermintBlock(block, blockRes) - n := hexutil.Uint(len(ethMsgs)) + n := hexutil.Uint(len(block.Block.Txs)) return &n } @@ -379,7 +368,21 @@ func (e *PublicAPI) GetCode(address common.Address, blockNrOrHash rpctypes.Block Address: address.String(), } - res, err := e.queryClient.Code(rpctypes.ContextWithHeight(blockNum.Int64()), req) + resBlock, err := e.backend.GetTendermintBlockByNumber(blockNum) + if err != nil { + return nil, err + } + + // return if requested block height is greater than the current one or chain not synced + if resBlock == nil || resBlock.Block == nil { + return nil, nil + } + + sdkCtx, err := e.backend.GetSdkContextWithHeader(&resBlock.Block.Header) + if err != nil { + return nil, err + } + res, err := e.backend.GetEVMKeeper().Code(sdk.WrapSDKContext(sdkCtx), req) if err != nil { return nil, err } @@ -392,7 +395,7 @@ func (e *PublicAPI) GetTransactionLogs(txHash common.Hash) ([]*ethtypes.Log, err e.logger.Debug("eth_getTransactionLogs", "hash", txHash) hexTx := txHash.Hex() - res, err := e.backend.GetTxByEthHash(txHash) + res, err := e.backend.GetTxByHash(txHash) if err != nil { e.logger.Debug("tx not found", "hash", hexTx, "error", err.Error()) return nil, nil @@ -508,36 +511,53 @@ func (e *PublicAPI) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) return common.Hash{}, err } + sdkCtx := e.backend.GetSdkContext() // Query params to use the EVM denomination - res, err := e.queryClient.QueryClient.Params(e.ctx, &evmtypes.QueryParamsRequest{}) - if err != nil { - e.logger.Error("failed to query evm params", "error", err.Error()) - return common.Hash{}, err - } + params := e.backend.GetEVMKeeper().GetParams(sdkCtx) - cosmosTx, err := ethereumTx.BuildTx(e.clientCtx.TxConfig.NewTxBuilder(), res.Params.EvmDenom) + cosmosTx, err := ethereumTx.BuildTx(e.clientCtx.TxConfig.NewTxBuilder(), params.EvmDenom) if err != nil { e.logger.Error("failed to build cosmos tx", "error", err.Error()) return common.Hash{}, err } // Encode transaction by default Tx encoder - txBytes, err := e.clientCtx.TxConfig.TxEncoder()(cosmosTx) + packet, err := e.clientCtx.TxConfig.TxEncoder()(cosmosTx) if err != nil { e.logger.Error("failed to encode eth tx using default encoder", "error", err.Error()) return common.Hash{}, err } - txHash := ethereumTx.AsTransaction().Hash() - - syncCtx := e.clientCtx.WithBroadcastMode(flags.BroadcastSync) - rsp, err := syncCtx.BroadcastTx(txBytes) - if rsp != nil && rsp.Code != 0 { - err = sdkerrors.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog) + ethTx := ethereumTx.AsTransaction() + if !ethTx.Protected() { + // Ensure only eip155 signed transactions are submitted. + return common.Hash{}, errors.New("legacy pre-eip-155 transactions not supported") } - if err != nil { - e.logger.Error("failed to broadcast tx", "error", err.Error()) - return txHash, err + txHash := ethTx.Hash() + + mempool := e.backend.GetMempool() + if e.clientCtx.BroadcastMode == "async" { + e.logger.Info("Use async mode to propagate tx", txHash) + err = mempool.CheckTx(packet, nil, mempl.TxInfo{}) + if err != nil { + return common.Hash{}, err + } + } else { + e.logger.Info("Use sync mode to propagate tx", txHash) + resCh := make(chan *abci.Response, 1) + err = mempool.CheckTx(packet, func(res *abci.Response) { + resCh <- res + }, mempl.TxInfo{}) + if err != nil { + e.logger.Error("failed to send eth tx packet to mempool", "error", err.Error()) + return common.Hash{}, err + } + res := <-resCh + resBrodTx := res.GetCheckTx() + if resBrodTx.Code != 0 { + e.logger.Error("exec failed on check tx", "error", resBrodTx.Log) + return common.Hash{}, fmt.Errorf(resBrodTx.Log) + } } return txHash, nil @@ -658,12 +678,27 @@ func (e *PublicAPI) doCall( GasCap: e.backend.RPCGasCap(), } - // From ContextWithHeight: if the provided height is 0, + resBlock, err := e.backend.GetTendermintBlockByNumber(blockNr) + if err != nil { + return nil, err + } + + // return if requested block height is greater than the current one or chain not synced + if resBlock == nil || resBlock.Block == nil { + return nil, nil + } + + sdkCtx, err := e.backend.GetSdkContextWithHeader(&resBlock.Block.Header) + if err != nil { + return nil, err + } + // it will return an empty context and the gRPC query will use // the latest block height for querying. - ctx := rpctypes.ContextWithHeight(blockNr.Int64()) timeout := e.backend.RPCEVMTimeout() + ctx := sdk.WrapSDKContext(sdkCtx) + // Setup context so it may be canceled the call has completed // or, in case of unmetered gas, setup a context with a timeout. var cancel context.CancelFunc @@ -677,7 +712,7 @@ func (e *PublicAPI) doCall( // this makes sure resources are cleaned up. defer cancel() - res, err := e.queryClient.EthCall(ctx, &req) + res, err := e.backend.GetEVMKeeper().EthCall(ctx, &req) if err != nil { return nil, err } @@ -699,77 +734,50 @@ func (e *PublicAPI) EstimateGas(args evmtypes.TransactionArgs, blockNrOptional * } // GetBlockByHash returns the block identified by hash. -func (e *PublicAPI) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) { +func (e *PublicAPI) GetBlockByHash(hash common.Hash, fullTx bool) (*types.Block, error) { e.logger.Debug("eth_getBlockByHash", "hash", hash.Hex(), "full", fullTx) return e.backend.GetBlockByHash(hash, fullTx) } // GetBlockByNumber returns the block identified by number. -func (e *PublicAPI) GetBlockByNumber(ethBlockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) { +func (e *PublicAPI) GetBlockByNumber(ethBlockNum rpctypes.BlockNumber, fullTx bool) (*types.Block, error) { e.logger.Debug("eth_getBlockByNumber", "number", ethBlockNum, "full", fullTx) return e.backend.GetBlockByNumber(ethBlockNum, fullTx) } // GetTransactionByHash returns the transaction identified by hash. -func (e *PublicAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.RPCTransaction, error) { +func (e *PublicAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.Transaction, error) { e.logger.Debug("eth_getTransactionByHash", "hash", hash.Hex()) return e.backend.GetTransactionByHash(hash) } // getTransactionByBlockAndIndex is the common code shared by `GetTransactionByBlockNumberAndIndex` and `GetTransactionByBlockHashAndIndex`. -func (e *PublicAPI) getTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { - var msg *evmtypes.MsgEthereumTx - // try /tx_search first - res, err := e.backend.GetTxByTxIndex(block.Block.Height, uint(idx)) - if err == nil { - tx, err := e.clientCtx.TxConfig.TxDecoder()(res.Tx) - if err != nil { - e.logger.Debug("invalid ethereum tx", "height", block.Block.Header, "index", idx) - return nil, nil - } - // find msg index in events - msgIndex := rpctypes.FindTxAttributesByIndex(res.TxResult.Events, uint64(idx)) - if msgIndex < 0 { - e.logger.Debug("invalid ethereum tx", "height", block.Block.Header, "index", idx) - return nil, nil - } - var ok bool - // msgIndex is inferred from tx events, should be within bound. - msg, ok = tx.GetMsgs()[msgIndex].(*evmtypes.MsgEthereumTx) - if !ok { - e.logger.Debug("invalid ethereum tx", "height", block.Block.Header, "index", idx) - return nil, nil - } - } else { - blockRes, err := e.clientCtx.Client.BlockResults(e.ctx, &block.Block.Height) - if err != nil { - return nil, nil - } +func (e *PublicAPI) getTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, idx hexutil.Uint) (*rpctypes.Transaction, error) { + // return if index out of bounds + if uint64(idx) >= uint64(len(block.Block.Txs)) { + return nil, nil + } - i := int(idx) - ethMsgs := e.backend.GetEthereumMsgsFromTendermintBlock(block, blockRes) - if i >= len(ethMsgs) { - e.logger.Debug("block txs index out of bound", "index", i) - return nil, nil - } + tx := block.Block.Txs[idx] - msg = ethMsgs[i] - } + blockHash := common.BytesToHash(block.Block.Hash()) + blockHeight := uint64(block.Block.Height) + txIndex := uint64(idx) - return rpctypes.NewTransactionFromMsg( - msg, - common.BytesToHash(block.Block.Hash()), - uint64(block.Block.Height), - uint64(idx), - e.chainIDEpoch, + return rpctypes.TmTxToEthTx( + e.clientCtx.TxConfig.TxDecoder(), + tx, + &blockHash, + &blockHeight, + &txIndex, ) } // GetTransactionByBlockHashAndIndex returns the transaction identified by hash and index. -func (e *PublicAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { +func (e *PublicAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.Transaction, error) { e.logger.Debug("eth_getTransactionByBlockHashAndIndex", "hash", hash.Hex(), "index", idx) - block, err := e.clientCtx.Client.BlockByHash(e.ctx, hash.Bytes()) + block, err := tmrpccore.BlockByHash(nil, hash.Bytes()) if err != nil { e.logger.Debug("block not found", "hash", hash.Hex(), "error", err.Error()) return nil, nil @@ -784,10 +792,10 @@ func (e *PublicAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexu } // GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index. -func (e *PublicAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { +func (e *PublicAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.Transaction, error) { e.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) - block, err := e.clientCtx.Client.Block(e.ctx, blockNum.TmHeight()) + block, err := tmrpccore.Block(nil, blockNum.TmHeight()) if err != nil { e.logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error()) return nil, nil @@ -802,150 +810,113 @@ func (e *PublicAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockN } // GetTransactionReceipt returns the transaction receipt identified by hash. -func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) { - hexTx := hash.Hex() - e.logger.Debug("eth_getTransactionReceipt", "hash", hexTx) - - res, err := e.backend.GetTxByEthHash(hash) +func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (*rpctypes.TransactionReceipt, error) { + e.logger.Debug("eth_getTransactionReceipt", "hash", hash) + res, err := e.backend.GetTxByHash(hash) if err != nil { - e.logger.Debug("tx not found", "hash", hexTx, "error", err.Error()) return nil, nil } - msgIndex, attrs := rpctypes.FindTxAttributes(res.TxResult.Events, hexTx) - if msgIndex < 0 { - return nil, fmt.Errorf("ethereum tx not found in msgs: %s", hexTx) - } - - resBlock, err := e.clientCtx.Client.Block(e.ctx, &res.Height) - if err != nil { - e.logger.Debug("block not found", "height", res.Height, "error", err.Error()) + block := e.backend.GetBlockStore().LoadBlock(res.Height) + if block == nil { + e.logger.Debug("eth_getTransactionReceipt", "hash", hash, "block not found") return nil, nil } - tx, err := e.clientCtx.TxConfig.TxDecoder()(res.Tx) + blockResults, err := tmrpccore.BlockResults(nil, &block.Height) if err != nil { - e.logger.Debug("decoding failed", "error", err.Error()) - return nil, fmt.Errorf("failed to decode tx: %w", err) + e.logger.Debug("eth_getTransactionReceipt", "hash", hash, "block not found") + return nil, nil } - // the `msgIndex` is inferred from tx events, should be within the bound. - msg := tx.GetMsgs()[msgIndex] - ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) - if !ok { - e.logger.Debug(fmt.Sprintf("invalid tx type: %T", msg)) - return nil, fmt.Errorf("invalid tx type: %T", msg) - } + blockHash := common.BytesToHash(block.Hash()) + blockHeight := uint64(res.Height) + txIndex := uint64(res.Index) - txData, err := evmtypes.UnpackTxData(ethMsg.Data) + rpcTx, err := rpctypes.TmTxToEthTx( + e.clientCtx.TxConfig.TxDecoder(), + res.Tx, + &blockHash, + &blockHeight, + &txIndex, + ) if err != nil { - e.logger.Error("failed to unpack tx data", "error", err.Error()) return nil, err } - cumulativeGasUsed := uint64(0) - blockRes, err := e.clientCtx.Client.BlockResults(e.ctx, &res.Height) - if err != nil { - e.logger.Debug("failed to retrieve block results", "height", res.Height, "error", err.Error()) - return nil, nil + cumulativeGasUsed := uint64(res.TxResult.GasUsed) + if *rpcTx.TransactionIndex != 0 { + cumulativeGasUsed += rpctypes.GetBlockCumulativeGas(blockResults, int(*rpcTx.TransactionIndex)) } - for i := 0; i < int(res.Index) && i < len(blockRes.TxsResults); i++ { - cumulativeGasUsed += uint64(blockRes.TxsResults[i].GasUsed) - } - cumulativeGasUsed += rpctypes.AccumulativeGasUsedOfMsg(res.TxResult.Events, msgIndex) + _, attrs := rpctypes.FindTxAttributes(res.TxResult.Events, hash.Hex()) - var gasUsed uint64 - if len(tx.GetMsgs()) == 1 { - // backward compatibility - gasUsed = uint64(res.TxResult.GasUsed) + var ( + contractAddress *common.Address + bloom = ethtypes.BytesToBloom(make([]byte, 6)) + logs = make([]*ethtypes.Log, 0) + ) + // Set status codes based on tx result + status := ethtypes.ReceiptStatusSuccessful + if res.TxResult.GetCode() == 1 { + status = ethtypes.ReceiptStatusFailed } else { - gasUsed, err = rpctypes.GetUint64Attribute(attrs, evmtypes.AttributeKeyTxGasUsed) - if err != nil { - return nil, err + // Get the transaction result from the log + _, found := attrs[evmtypes.AttributeKeyEthereumTxFailed] + if found { + status = ethtypes.ReceiptStatusFailed } - } - // Get the transaction result from the log - _, found := attrs[evmtypes.AttributeKeyEthereumTxFailed] - var status hexutil.Uint - if found { - status = hexutil.Uint(ethtypes.ReceiptStatusFailed) - } else { - status = hexutil.Uint(ethtypes.ReceiptStatusSuccessful) - } - - from, err := ethMsg.GetSender(e.chainIDEpoch) - if err != nil { - return nil, err - } - - // parse tx logs from events - logs, err := backend.TxLogsFromEvents(res.TxResult.Events, msgIndex) - if err != nil { - e.logger.Debug("logs not found", "hash", hexTx, "error", err.Error()) - } - - // Try to find txIndex from events - found = false - txIndex, err := rpctypes.GetUint64Attribute(attrs, evmtypes.AttributeKeyTxIndex) - if err == nil { - found = true - } else { - // Fallback to find tx index by iterating all valid eth transactions - msgs := e.backend.GetEthereumMsgsFromTendermintBlock(resBlock, blockRes) - for i := range msgs { - if msgs[i].Hash == hexTx { - txIndex = uint64(i) - found = true - break + if status == ethtypes.ReceiptStatusSuccessful { + // parse tx logs from events + logs, err = backend.TxLogsFromEvents(res.TxResult.Events, 0) + if err != nil { + e.logger.Debug("logs not found", "hash", hash, "error", err.Error()) + } + if logs == nil { + logs = make([]*ethtypes.Log, 0) + } + if rpcTx.To == nil { + // TODO: Rewrite on more optimal way in order to get a contract address + tx, err := e.clientCtx.TxConfig.TxDecoder()(res.Tx) + if err != nil { + e.logger.Debug("decoding failed", "error", err.Error()) + return nil, fmt.Errorf("failed to decode tx: %w", err) + } + + // the `msgIndex` is inferred from tx events, should be within the bound. + msg := tx.GetMsgs()[0] + ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) + if !ok { + e.logger.Debug(fmt.Sprintf("invalid tx type: %T", msg)) + return nil, fmt.Errorf("invalid tx type: %T", msg) + } + + txData, err := evmtypes.UnpackTxData(ethMsg.Data) + if err != nil { + e.logger.Error("failed to unpack tx data", "error", err.Error()) + return nil, err + } + contractAddress = new(common.Address) + *contractAddress = crypto.CreateAddress(rpcTx.From, txData.GetNonce()) } + bloom = ethtypes.BytesToBloom(ethtypes.LogsBloom(logs)) } } - if !found { - return nil, errors.New("can't find index of ethereum tx") - } - - receipt := map[string]interface{}{ - // Consensus fields: These fields are defined by the Yellow Paper - "status": status, - "cumulativeGasUsed": hexutil.Uint64(cumulativeGasUsed), - "logsBloom": ethtypes.BytesToBloom(ethtypes.LogsBloom(logs)), - "logs": logs, - - // Implementation fields: These fields are added by geth when processing a transaction. - // They are stored in the chain database. - "transactionHash": hash, - "contractAddress": nil, - "gasUsed": hexutil.Uint64(gasUsed), - "type": hexutil.Uint(txData.TxType()), - // Inclusion information: These fields provide information about the inclusion of the - // transaction corresponding to this receipt. - "blockHash": common.BytesToHash(resBlock.Block.Header.Hash()).Hex(), - "blockNumber": hexutil.Uint64(res.Height), - "transactionIndex": hexutil.Uint64(txIndex), - - // sender and receiver (contract or EOA) addreses - "from": from, - "to": txData.GetTo(), - } - - if logs == nil { - receipt["logs"] = [][]*ethtypes.Log{} - } - - // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation - if txData.GetTo() == nil { - receipt["contractAddress"] = crypto.CreateAddress(from, txData.GetNonce()) - } - - if dynamicTx, ok := txData.(*evmtypes.DynamicFeeTx); ok { - baseFee, err := e.backend.BaseFee(res.Height) - if err != nil { - return nil, err - } - receipt["effectiveGasPrice"] = hexutil.Big(*dynamicTx.GetEffectiveGasPrice(baseFee)) + receipt := &rpctypes.TransactionReceipt{ + Status: hexutil.Uint64(status), + CumulativeGasUsed: hexutil.Uint64(cumulativeGasUsed), + LogsBloom: bloom, + Logs: logs, + TransactionHash: rpcTx.Hash, + ContractAddress: contractAddress, + GasUsed: hexutil.Uint64(res.TxResult.GasUsed), + BlockHash: *rpcTx.BlockHash, + BlockNumber: *rpcTx.BlockNumber, + TransactionIndex: *rpcTx.TransactionIndex, + From: rpcTx.From, + To: rpcTx.To, } return receipt, nil @@ -953,36 +924,19 @@ func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (map[string]interfac // GetPendingTransactions returns the transactions that are in the transaction pool // and have a from address that is one of the accounts this node manages. -func (e *PublicAPI) GetPendingTransactions() ([]*rpctypes.RPCTransaction, error) { +func (e *PublicAPI) GetPendingTransactions() ([]*rpctypes.Transaction, error) { e.logger.Debug("eth_getPendingTransactions") - txs, err := e.backend.PendingTransactions() - if err != nil { - return nil, err - } + txs := e.backend.GetMempool().ReapMaxTxs(100) - result := make([]*rpctypes.RPCTransaction, 0, len(txs)) + result := make([]*rpctypes.Transaction, 0, len(txs)) for _, tx := range txs { - for _, msg := range (*tx).GetMsgs() { - ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) - if !ok { - // not valid ethereum tx - break - } - - rpctx, err := rpctypes.NewTransactionFromMsg( - ethMsg, - common.Hash{}, - uint64(0), - uint64(0), - e.chainIDEpoch, - ) - if err != nil { - return nil, err - } - - result = append(result, rpctx) + rpctx, err := rpctypes.TmTxToEthTx(e.clientCtx.TxConfig.TxDecoder(), tx, nil, nil, nil) + if err != nil { + return nil, err } + + result = append(result, rpctx) } return result, nil @@ -1008,7 +962,6 @@ func (e *PublicAPI) GetProof(address common.Address, storageKeys []string, block } height := blockNum.Int64() - ctx := rpctypes.ContextWithHeight(height) // if the height is equal to zero, meaning the query condition of the block is either "pending" or "latest" if height == 0 { @@ -1024,14 +977,27 @@ func (e *PublicAPI) GetProof(address common.Address, storageKeys []string, block height = int64(bn) } - clientCtx := e.clientCtx.WithHeight(height) - // query storage proofs storageProofs := make([]rpctypes.StorageResult, len(storageKeys)) + resBlock, err := e.backend.GetTendermintBlockByNumber(blockNum) + if err != nil { + return nil, err + } + + // return if requested block height is greater than the current one or chain not synced + if resBlock == nil || resBlock.Block == nil { + return nil, nil + } + + sdkCtx, err := e.backend.GetSdkContextWithHeader(&resBlock.Block.Header) + if err != nil { + return nil, err + } + for i, key := range storageKeys { hexKey := common.HexToHash(key) - valueBz, proof, err := e.queryClient.GetProof(clientCtx, evmtypes.StoreKey, evmtypes.StateKey(address, hexKey.Bytes())) + valueBz, proof, err := types.GetProof(height, evmtypes.StoreKey, evmtypes.StateKey(address, hexKey.Bytes())) if err != nil { return nil, err } @@ -1050,18 +1016,11 @@ func (e *PublicAPI) GetProof(address common.Address, storageKeys []string, block } // query EVM account - req := &evmtypes.QueryAccountRequest{ - Address: address.String(), - } - - res, err := e.queryClient.Account(ctx, req) - if err != nil { - return nil, err - } + acc := e.backend.GetEVMKeeper().GetAccountOrEmpty(sdkCtx, address) // query account proofs accountKey := authtypes.AddressStoreKey(sdk.AccAddress(address.Bytes())) - _, proof, err := e.queryClient.GetProof(clientCtx, authtypes.StoreKey, accountKey) + _, proof, err := types.GetProof(height, authtypes.StoreKey, accountKey) if err != nil { return nil, err } @@ -1072,17 +1031,12 @@ func (e *PublicAPI) GetProof(address common.Address, storageKeys []string, block accProofStr = proof.String() } - balance, ok := sdk.NewIntFromString(res.Balance) - if !ok { - return nil, errors.New("invalid balance") - } - return &rpctypes.AccountResult{ Address: address, AccountProof: []string{accProofStr}, - Balance: (*hexutil.Big)(balance.BigInt()), - CodeHash: common.HexToHash(res.CodeHash), - Nonce: hexutil.Uint64(res.Nonce), + Balance: (*hexutil.Big)(acc.Balance), + CodeHash: common.BytesToHash(acc.CodeHash), + Nonce: hexutil.Uint64(acc.Nonce), StorageHash: common.Hash{}, // NOTE: stratos doesn't have a storage hash. TODO: implement? StorageProof: storageProofs, }, nil diff --git a/rpc/namespaces/ethereum/eth/filters/api.go b/rpc/namespaces/ethereum/eth/filters/api.go index 11f6867c..ccadf761 100644 --- a/rpc/namespaces/ethereum/eth/filters/api.go +++ b/rpc/namespaces/ethereum/eth/filters/api.go @@ -8,7 +8,6 @@ import ( "github.com/tendermint/tendermint/libs/log" coretypes "github.com/tendermint/tendermint/rpc/core/types" - rpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client" tmtypes "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/client" @@ -18,26 +17,11 @@ import ( "github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/rpc" + "github.com/stratosnet/stratos-chain/rpc/backend" "github.com/stratosnet/stratos-chain/rpc/types" evmtypes "github.com/stratosnet/stratos-chain/x/evm/types" ) -// Backend defines the methods requided by the PublicFilterAPI backend -type Backend interface { - GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error) - HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header, error) - HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) - GetLogs(blockHash common.Hash) ([][]*ethtypes.Log, error) - GetLogsByNumber(blockNum types.BlockNumber) ([][]*ethtypes.Log, error) - BlockBloom(height *int64) (ethtypes.Bloom, error) - - BloomStatus() (uint64, uint64) - - RPCFilterCap() int32 - RPCLogsCap() int32 - RPCBlockRangeCap() int32 -} - // consider a filter inactive if it has not been polled for within deadline var deadline = 5 * time.Minute @@ -57,21 +41,21 @@ type filter struct { type PublicFilterAPI struct { logger log.Logger clientCtx client.Context - backend Backend + backend backend.BackendI events *EventSystem filtersMu sync.Mutex filters map[rpc.ID]*filter } // NewPublicAPI returns a new PublicFilterAPI instance. -func NewPublicAPI(logger log.Logger, clientCtx client.Context, tmWSClient *rpcclient.WSClient, backend Backend) *PublicFilterAPI { +func NewPublicAPI(logger log.Logger, clientCtx client.Context, eventBus *tmtypes.EventBus, b backend.BackendI) *PublicFilterAPI { logger = logger.With("api", "filter") api := &PublicFilterAPI{ logger: logger, clientCtx: clientCtx, - backend: backend, + backend: b, filters: make(map[rpc.ID]*filter), - events: NewEventSystem(logger, tmWSClient), + events: NewEventSystem(clientCtx, logger, eventBus), } go api.timeoutLoop() @@ -109,9 +93,6 @@ func (api *PublicFilterAPI) timeoutLoop() { // // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newPendingTransactionFilter func (api *PublicFilterAPI) NewPendingTransactionFilter() rpc.ID { - api.filtersMu.Lock() - defer api.filtersMu.Unlock() - if len(api.filters) >= int(api.backend.RPCFilterCap()) { return rpc.ID("error creating pending tx filter: max limit reached") } @@ -121,42 +102,32 @@ func (api *PublicFilterAPI) NewPendingTransactionFilter() rpc.ID { // wrap error on the ID return rpc.ID(fmt.Sprintf("error creating pending tx filter: %s", err.Error())) } - + api.filtersMu.Lock() api.filters[pendingTxSub.ID()] = &filter{typ: filters.PendingTransactionsSubscription, deadline: time.NewTimer(deadline), hashes: make([]common.Hash, 0), s: pendingTxSub} + api.filtersMu.Unlock() go func(txsCh <-chan coretypes.ResultEvent, errCh <-chan error) { defer cancelSubs() for { select { - case ev, ok := <-txsCh: - if !ok { - api.filtersMu.Lock() - delete(api.filters, pendingTxSub.ID()) - api.filtersMu.Unlock() - return - } - + case ev := <-txsCh: data, ok := ev.Data.(tmtypes.EventDataTx) if !ok { - api.logger.Debug("event data type mismatch", "type", fmt.Sprintf("%T", ev.Data)) - continue + err = fmt.Errorf("invalid event data %T, expected %s", ev.Data, tmtypes.EventTx) + pendingTxSub.err <- err + return } - tx, err := api.clientCtx.TxConfig.TxDecoder()(data.Tx) + txHash, err := types.GetTxHash(api.clientCtx.TxConfig.TxDecoder(), tmtypes.Tx(data.Tx)) if err != nil { - api.logger.Debug("fail to decode tx", "error", err.Error()) - continue + pendingTxSub.err <- err + return } api.filtersMu.Lock() if f, found := api.filters[pendingTxSub.ID()]; found { - for _, msg := range tx.GetMsgs() { - ethTx, ok := msg.(*evmtypes.MsgEthereumTx) - if ok { - f.hashes = append(f.hashes, common.HexToHash(ethTx.Hash)) - } - } + f.hashes = append(f.hashes, txHash) } api.filtersMu.Unlock() case <-errCh: @@ -195,31 +166,25 @@ func (api *PublicFilterAPI) NewPendingTransactions(ctx context.Context) (*rpc.Su for { select { - case ev, ok := <-txsCh: - if !ok { - api.filtersMu.Lock() - delete(api.filters, pendingTxSub.ID()) - api.filtersMu.Unlock() - return - } - + case ev := <-txsCh: data, ok := ev.Data.(tmtypes.EventDataTx) if !ok { - api.logger.Debug("event data type mismatch", "type", fmt.Sprintf("%T", ev.Data)) - continue + err = fmt.Errorf("invalid event data %T, expected %s", ev.Data, tmtypes.EventTx) + pendingTxSub.err <- err + return } - tx, err := api.clientCtx.TxConfig.TxDecoder()(data.Tx) + txHash, err := types.GetTxHash(api.clientCtx.TxConfig.TxDecoder(), tmtypes.Tx(data.Tx)) if err != nil { - api.logger.Debug("fail to decode tx", "error", err.Error()) - continue + pendingTxSub.err <- err + return } - for _, msg := range tx.GetMsgs() { - ethTx, ok := msg.(*evmtypes.MsgEthereumTx) - if ok { - _ = notifier.Notify(rpcSub.ID, common.HexToHash(ethTx.Hash)) - } + // To keep the original behaviour, send a single tx hash in one notification. + // TODO(rjl493456442) Send a batch of tx hashes in one notification + err = notifier.Notify(rpcSub.ID, txHash) + if err != nil { + return } case <-rpcSub.Err(): pendingTxSub.Unsubscribe(api.events) @@ -239,58 +204,62 @@ func (api *PublicFilterAPI) NewPendingTransactions(ctx context.Context) (*rpc.Su // // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newblockfilter func (api *PublicFilterAPI) NewBlockFilter() rpc.ID { - api.filtersMu.Lock() - defer api.filtersMu.Unlock() - - if len(api.filters) >= int(api.backend.RPCFilterCap()) { - return rpc.ID("error creating block filter: max limit reached") - } - - headerSub, cancelSubs, err := api.events.SubscribeNewHeads() + headersSub, cancelSubs, err := api.events.SubscribeNewHeads() if err != nil { // wrap error on the ID return rpc.ID(fmt.Sprintf("error creating block filter: %s", err.Error())) } - api.filters[headerSub.ID()] = &filter{typ: filters.BlocksSubscription, deadline: time.NewTimer(deadline), hashes: []common.Hash{}, s: headerSub} + api.filtersMu.Lock() + api.filters[headersSub.ID()] = &filter{typ: filters.BlocksSubscription, deadline: time.NewTimer(deadline), hashes: []common.Hash{}, s: headersSub} + api.filtersMu.Unlock() go func(headersCh <-chan coretypes.ResultEvent, errCh <-chan error) { defer cancelSubs() for { select { - case ev, ok := <-headersCh: + case ev := <-headersCh: + data, ok := ev.Data.(tmtypes.EventDataNewBlockHeader) if !ok { - api.filtersMu.Lock() - delete(api.filters, headerSub.ID()) - api.filtersMu.Unlock() + err = fmt.Errorf("invalid event data %T, expected %s", ev.Data, tmtypes.EventNewBlockHeader) + headersSub.err <- err return } - - data, ok := ev.Data.(tmtypes.EventDataNewBlockHeader) - if !ok { - api.logger.Debug("event data type mismatch", "type", fmt.Sprintf("%T", ev.Data)) - continue + header, err := types.EthHeaderFromTendermint(data.Header) + if err != nil { + headersSub.err <- err + return + } + // override dynamicly miner address + sdkCtx, err := api.backend.GetSdkContextWithHeader(&data.Header) + if err != nil { + headersSub.err <- err + return } - baseFee := types.BaseFeeFromEvents(data.ResultBeginBlock.Events) + validator, err := api.backend.GetEVMKeeper().GetCoinbaseAddress(sdkCtx) + if err != nil { + headersSub.err <- err + return + } + header.Coinbase = validator - header := types.EthHeaderFromTendermint(data.Header, ethtypes.Bloom{}, baseFee) api.filtersMu.Lock() - if f, found := api.filters[headerSub.ID()]; found { - f.hashes = append(f.hashes, header.Hash()) + if f, found := api.filters[headersSub.ID()]; found { + f.hashes = append(f.hashes, header.Hash) } api.filtersMu.Unlock() case <-errCh: api.filtersMu.Lock() - delete(api.filters, headerSub.ID()) + delete(api.filters, headersSub.ID()) api.filtersMu.Unlock() return } } - }(headerSub.eventCh, headerSub.Err()) + }(headersSub.eventCh, headersSub.Err()) - return headerSub.ID() + return headersSub.ID() } // NewHeads send a notification each time a new (header) block is appended to the chain. @@ -313,23 +282,38 @@ func (api *PublicFilterAPI) NewHeads(ctx context.Context) (*rpc.Subscription, er for { select { - case ev, ok := <-headersCh: + case ev := <-headersCh: + data, ok := ev.Data.(tmtypes.EventDataNewBlockHeader) if !ok { - headersSub.Unsubscribe(api.events) + err = fmt.Errorf("invalid event data %T, expected %s", ev.Data, tmtypes.EventNewBlockHeader) + headersSub.err <- err return } - data, ok := ev.Data.(tmtypes.EventDataNewBlockHeader) - if !ok { - api.logger.Debug("event data type mismatch", "type", fmt.Sprintf("%T", ev.Data)) - continue + header, err := types.EthHeaderFromTendermint(data.Header) + if err != nil { + headersSub.err <- err + return + } + // override dynamicly miner address + sdkCtx, err := api.backend.GetSdkContextWithHeader(&data.Header) + if err != nil { + headersSub.err <- err + return } - baseFee := types.BaseFeeFromEvents(data.ResultBeginBlock.Events) + validator, err := api.backend.GetEVMKeeper().GetCoinbaseAddress(sdkCtx) + if err != nil { + headersSub.err <- err + return + } + header.Coinbase = validator - // TODO: fetch bloom from events - header := types.EthHeaderFromTendermint(data.Header, ethtypes.Bloom{}, baseFee) - _ = notifier.Notify(rpcSub.ID, header) + err = notifier.Notify(rpcSub.ID, header) + if err != nil { + headersSub.err <- err + return + } case <-rpcSub.Err(): headersSub.Unsubscribe(api.events) return @@ -363,36 +347,38 @@ func (api *PublicFilterAPI) Logs(ctx context.Context, crit filters.FilterCriteri for { select { - case ev, ok := <-logsCh: - if !ok { - logsSub.Unsubscribe(api.events) - return - } - - // filter only events from EVM module txs - _, isMsgEthereumTx := ev.Events[evmtypes.TypeMsgEthereumTx] - + case ev := <-logsCh: + _, isMsgEthereumTx := ev.Events[fmt.Sprintf("%s.%s", evmtypes.EventTypeEthereumTx, evmtypes.AttributeKeyEthereumTxHash)] + api.logger.Debug("\x1b[32m------ logs tx type is evm from sub: %t\x1b[0m\n", isMsgEthereumTx) if !isMsgEthereumTx { - // ignore transaction as it's not from the evm module - return + continue } // get transaction result data dataTx, ok := ev.Data.(tmtypes.EventDataTx) if !ok { - api.logger.Debug("event data type mismatch", "type", fmt.Sprintf("%T", ev.Data)) - continue + err = fmt.Errorf("invalid event data %T, expected %s", ev.Data, tmtypes.EventTx) + logsSub.err <- err + return } + api.logger.Debug("\x1b[32m------ logs tx dataTx: %+v\x1b[0m\n", dataTx) txResponse, err := evmtypes.DecodeTxResponse(dataTx.TxResult.Result.Data) if err != nil { + logsSub.err <- err return } - - logs := FilterLogs(evmtypes.LogsToEthereum(txResponse.Logs), crit.FromBlock, crit.ToBlock, crit.Addresses, crit.Topics) - - for _, log := range logs { - _ = notifier.Notify(rpcSub.ID, log) + api.logger.Debug("\x1b[32m------ logs tx response: %+v\x1b[0m\n", txResponse) + api.logger.Debug("\x1b[32m------ logs crit: %+v\x1b[0m\n", crit) + + matchedLogs := FilterLogs(evmtypes.LogsToEthereum(txResponse.Logs), crit.FromBlock, crit.ToBlock, crit.Addresses, crit.Topics) + api.logger.Debug("\x1b[32m------ logs matchedLogs: %+v\x1b[0m\n", matchedLogs) + for _, log := range matchedLogs { + err = notifier.Notify(rpcSub.ID, log) + if err != nil { + logsSub.err <- err + return + } } case <-rpcSub.Err(): // client send an unsubscribe request logsSub.Unsubscribe(api.events) @@ -421,9 +407,6 @@ func (api *PublicFilterAPI) Logs(ctx context.Context, crit filters.FilterCriteri // // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newfilter func (api *PublicFilterAPI) NewFilter(criteria filters.FilterCriteria) (rpc.ID, error) { - api.filtersMu.Lock() - defer api.filtersMu.Unlock() - if len(api.filters) >= int(api.backend.RPCFilterCap()) { return rpc.ID(""), fmt.Errorf("error creating filter: max limit reached") } @@ -440,28 +423,31 @@ func (api *PublicFilterAPI) NewFilter(criteria filters.FilterCriteria) (rpc.ID, filterID = logsSub.ID() + api.filtersMu.Lock() api.filters[filterID] = &filter{typ: filters.LogsSubscription, crit: criteria, deadline: time.NewTimer(deadline), hashes: []common.Hash{}, s: logsSub} + api.filtersMu.Unlock() go func(eventCh <-chan coretypes.ResultEvent) { defer cancelSubs() for { select { - case ev, ok := <-eventCh: - if !ok { - api.filtersMu.Lock() - delete(api.filters, filterID) - api.filtersMu.Unlock() - return + case ev := <-eventCh: + _, isMsgEthereumTx := ev.Events[fmt.Sprintf("%s.%s", evmtypes.EventTypeEthereumTx, evmtypes.AttributeKeyEthereumTxHash)] + if !isMsgEthereumTx { + continue } + dataTx, ok := ev.Data.(tmtypes.EventDataTx) if !ok { - api.logger.Debug("event data type mismatch", "type", fmt.Sprintf("%T", ev.Data)) - continue + err = fmt.Errorf("invalid event data %T, expected EventDataTx", ev.Data) + logsSub.err <- err + return } txResponse, err := evmtypes.DecodeTxResponse(dataTx.TxResult.Result.Data) if err != nil { + logsSub.err <- err return } @@ -612,3 +598,8 @@ func (api *PublicFilterAPI) GetFilterChanges(id rpc.ID) (interface{}, error) { return nil, fmt.Errorf("invalid filter %s type %d", id, f.typ) } } + +// Syncing provides information when this nodes starts synchronising with the OneLedger network and when it's finished. +func (api *PublicFilterAPI) Syncing() (*rpc.Subscription, error) { + return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported +} diff --git a/rpc/namespaces/ethereum/eth/filters/filter_system.go b/rpc/namespaces/ethereum/eth/filters/filter_system.go index a8b0ec72..6cb8e06c 100644 --- a/rpc/namespaces/ethereum/eth/filters/filter_system.go +++ b/rpc/namespaces/ethereum/eth/filters/filter_system.go @@ -6,13 +6,12 @@ import ( "sync" "time" + "github.com/cosmos/cosmos-sdk/client" "github.com/pkg/errors" - - tmjson "github.com/tendermint/tendermint/libs/json" "github.com/tendermint/tendermint/libs/log" + tmpubsub "github.com/tendermint/tendermint/libs/pubsub" tmquery "github.com/tendermint/tendermint/libs/pubsub/query" coretypes "github.com/tendermint/tendermint/rpc/core/types" - rpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client" tmtypes "github.com/tendermint/tendermint/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -22,34 +21,48 @@ import ( "github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/rpc" - "github.com/stratosnet/stratos-chain/rpc/ethereum/pubsub" + "github.com/stratosnet/stratos-chain/rpc/types" evmtypes "github.com/stratosnet/stratos-chain/x/evm/types" ) var ( - txEvents = tmtypes.QueryForEvent(tmtypes.EventTx).String() - evmEvents = tmquery.MustParse(fmt.Sprintf("%s='%s' AND %s.%s='%s'", tmtypes.EventTypeKey, tmtypes.EventTx, sdk.EventTypeMessage, sdk.AttributeKeyModule, evmtypes.ModuleName)).String() + // base tm tx event + txEvents = tmtypes.QueryForEvent(tmtypes.EventTx).String() + // listen only evm txs + evmEvents = tmquery.MustParse(fmt.Sprintf("%s='%s' AND %s.%s='%s'", tmtypes.EventTypeKey, tmtypes.EventTx, sdk.EventTypeMessage, sdk.AttributeKeyModule, evmtypes.ModuleName)).String() + // specify to listen a blocks instead of heads as it contain more details about the block header including current block hash headerEvents = tmtypes.QueryForEvent(tmtypes.EventNewBlockHeader).String() + // for tendermint subscribe channel capacity to make it buffered + tmChannelCapacity = 100 ) // EventSystem creates subscriptions, processes events and broadcasts them to the // subscription which match the subscription criteria using the Tendermint's RPC client. type EventSystem struct { - logger log.Logger - ctx context.Context - tmWSClient *rpcclient.WSClient - - // light client mode - lightMode bool + logger log.Logger + ctx context.Context + clientCtx client.Context index filterIndex topicChans map[string]chan<- coretypes.ResultEvent indexMux *sync.RWMutex + // Subscriptions + txsSub *Subscription // Subscription for new transaction event + logsSub *Subscription // Subscription for new log event + pendingLogsSub *Subscription // Subscription for pending log event + chainSub *Subscription // Subscription for new chain event + + // Unidirectional channels to receive Tendermint ResultEvents + txsCh <-chan coretypes.ResultEvent // Channel to receive new pending transactions event + logsCh <-chan coretypes.ResultEvent // Channel to receive new log event + pendingLogsCh <-chan coretypes.ResultEvent // Channel to receive new pending log event + chainCh <-chan coretypes.ResultEvent // Channel to receive new chain event + // Channels install chan *Subscription // install filter for event notification uninstall chan *Subscription // remove filter for event notification - eventBus pubsub.EventBus + eventBus *tmtypes.EventBus } // NewEventSystem creates a new manager that listens for event on the given mux, @@ -58,27 +71,29 @@ type EventSystem struct { // // The returned manager has a loop that needs to be stopped with the Stop function // or by stopping the given mux. -func NewEventSystem(logger log.Logger, tmWSClient *rpcclient.WSClient) *EventSystem { +func NewEventSystem(clientCtx client.Context, logger log.Logger, eventBus *tmtypes.EventBus) *EventSystem { index := make(filterIndex) for i := filters.UnknownSubscription; i < filters.LastIndexSubscription; i++ { index[i] = make(map[rpc.ID]*Subscription) } es := &EventSystem{ - logger: logger, - ctx: context.Background(), - tmWSClient: tmWSClient, - lightMode: false, - index: index, - topicChans: make(map[string]chan<- coretypes.ResultEvent, len(index)), - indexMux: new(sync.RWMutex), - install: make(chan *Subscription), - uninstall: make(chan *Subscription), - eventBus: pubsub.NewEventBus(), + logger: logger, + ctx: context.Background(), + clientCtx: clientCtx, + index: index, + topicChans: make(map[string]chan<- coretypes.ResultEvent, len(index)), + indexMux: new(sync.RWMutex), + install: make(chan *Subscription), + uninstall: make(chan *Subscription), + eventBus: eventBus, + txsCh: make(<-chan coretypes.ResultEvent), + logsCh: make(<-chan coretypes.ResultEvent), + pendingLogsCh: make(<-chan coretypes.ResultEvent), + chainCh: make(<-chan coretypes.ResultEvent), } go es.eventLoop() - go es.consumeEvents() return es } @@ -89,64 +104,128 @@ func (es *EventSystem) WithContext(ctx context.Context) { } // subscribe performs a new event subscription to a given Tendermint event. -// The subscription creates a unidirectional receive event channel to receive the ResultEvent. -func (es *EventSystem) subscribe(sub *Subscription) (*Subscription, pubsub.UnsubscribeFunc, error) { +// The subscription creates a unidirectional receive event channel to receive the ResultEvent. By +// default, the subscription timeouts (i.e is canceled) after 5 minutes. This function returns an +// error if the subscription fails (eg: if the identifier is already subscribed) or if the filter +// type is invalid. +func (es *EventSystem) subscribe(sub *Subscription) (*Subscription, context.CancelFunc, error) { var ( err error cancelFn context.CancelFunc + eventCh <-chan coretypes.ResultEvent ) - ctx, cancelFn := context.WithCancel(context.Background()) - defer cancelFn() - - existingSubs := es.eventBus.Topics() - for _, topic := range existingSubs { - if topic == sub.event { - eventCh, unsubFn, err := es.eventBus.Subscribe(sub.event) - if err != nil { - err := errors.Wrapf(err, "failed to subscribe to topic: %s", sub.event) - return nil, nil, err - } - - sub.eventCh = eventCh - return sub, unsubFn, nil - } - } + es.ctx, cancelFn = context.WithTimeout(context.Background(), deadline) switch sub.typ { - case filters.LogsSubscription: - err = es.tmWSClient.Subscribe(ctx, sub.event) - case filters.BlocksSubscription: - err = es.tmWSClient.Subscribe(ctx, sub.event) - case filters.PendingTransactionsSubscription: - err = es.tmWSClient.Subscribe(ctx, sub.event) + case + filters.PendingTransactionsSubscription, + filters.PendingLogsSubscription, + filters.MinedAndPendingLogsSubscription, + filters.LogsSubscription, + filters.BlocksSubscription: + + eventCh, err = es.createEventBusSubscription(string(sub.id), sub.event) default: err = fmt.Errorf("invalid filter subscription type %d", sub.typ) } if err != nil { sub.err <- err - return nil, nil, err + return nil, cancelFn, err } // wrap events in a go routine to prevent blocking - es.install <- sub - <-sub.installed + go func() { + es.install <- sub + <-sub.installed + }() + + sub.eventCh = eventCh + return sub, cancelFn, nil +} - eventCh, unsubFn, err := es.eventBus.Subscribe(sub.event) +func (es *EventSystem) createEventBusSubscription(subscriber, query string) (out <-chan coretypes.ResultEvent, err error) { + q, err := tmquery.New(query) if err != nil { - return nil, nil, errors.Wrapf(err, "failed to subscribe to topic after installed: %s", sub.event) + return nil, errors.Wrap(err, "failed to parse query") } - sub.eventCh = eventCh - return sub, unsubFn, nil + var sub tmtypes.Subscription + if tmChannelCapacity > 0 { + sub, err = es.eventBus.Subscribe(es.ctx, subscriber, q, tmChannelCapacity) + } else { + sub, err = es.eventBus.SubscribeUnbuffered(es.ctx, subscriber, q) + } + + if err != nil { + return nil, errors.Wrap(err, "failed to subscribe") + } + + outc := make(chan coretypes.ResultEvent, tmChannelCapacity) + go es.eventsRoutine(sub, subscriber, q, outc) + + return outc, nil +} + +func (es *EventSystem) eventsRoutine( + sub tmtypes.Subscription, + subscriber string, + q tmpubsub.Query, + outc chan<- coretypes.ResultEvent) { + for { + select { + case msg := <-sub.Out(): + result := coretypes.ResultEvent{Query: q.String(), Data: msg.Data(), Events: msg.Events()} + if cap(outc) == 0 { + outc <- result + } else { + select { + case outc <- result: + default: + // es.logger.Error("wanted to publish ResultEvent, but out channel is full", "result", result, "query", result.Query) + } + } + case <-sub.Cancelled(): + if sub.Err() == tmpubsub.ErrUnsubscribed { + return + } + + es.logger.Error("subscription was cancelled, resubscribing...", "err", sub.Err(), "query", q.String()) + sub = es.resubscribe(subscriber, q) + if sub == nil { // client was stopped + return + } + case <-es.eventBus.Quit(): + return + } + } +} + +// Try to resubscribe with exponential backoff. +func (es *EventSystem) resubscribe(subscriber string, q tmpubsub.Query) tmtypes.Subscription { + attempts := 0 + for { + if !es.eventBus.IsRunning() { + return nil + } + + sub, err := es.eventBus.Subscribe(context.Background(), subscriber, q) + if err == nil { + return sub + } + + attempts++ + time.Sleep((10 << uint(attempts)) * time.Millisecond) // 10ms -> 20ms -> 40ms + } } // SubscribeLogs creates a subscription that will write all logs matching the // given criteria to the given logs channel. Default value for the from and to // block is "latest". If the fromBlock > toBlock an error is returned. -func (es *EventSystem) SubscribeLogs(crit filters.FilterCriteria) (*Subscription, pubsub.UnsubscribeFunc, error) { +func (es *EventSystem) SubscribeLogs(crit filters.FilterCriteria) (*Subscription, context.CancelFunc, error) { var from, to rpc.BlockNumber + es.logger.Debug("\x1b[32m------ SubscribeLogs crit: %+v\x1b[0m\n", crit) if crit.FromBlock == nil { from = rpc.LatestBlockNumber } else { @@ -159,21 +238,44 @@ func (es *EventSystem) SubscribeLogs(crit filters.FilterCriteria) (*Subscription } switch { + // only interested in pending logs + case from == rpc.PendingBlockNumber && to == rpc.PendingBlockNumber: + return es.subscribePendingLogs(crit) + // only interested in new mined logs, mined logs within a specific block range, or // logs from a specific block number to new mined blocks case (from == rpc.LatestBlockNumber && to == rpc.LatestBlockNumber), - (from >= 0 && to >= 0 && to >= from), - (from >= 0 && to == rpc.LatestBlockNumber): + (from >= 0 && to >= 0 && to >= from): return es.subscribeLogs(crit) + // interested in mined logs from a specific block number, new logs and pending logs + case from >= rpc.LatestBlockNumber && (to == rpc.PendingBlockNumber || to == rpc.LatestBlockNumber): + return es.subscribeMinedPendingLogs(crit) + default: return nil, nil, fmt.Errorf("invalid from and to block combination: from > to (%d > %d)", from, to) } } +// subscribePendingLogs creates a subscription that writes transaction hashes for +// transactions that enter the transaction pool. +func (es *EventSystem) subscribePendingLogs(crit filters.FilterCriteria) (*Subscription, context.CancelFunc, error) { + sub := &Subscription{ + id: rpc.NewID(), + typ: filters.PendingLogsSubscription, + event: evmEvents, + logsCrit: crit, + created: time.Now().UTC(), + logs: make(chan []*ethtypes.Log), + installed: make(chan struct{}, 1), + err: make(chan error, 1), + } + return es.subscribe(sub) +} + // subscribeLogs creates a subscription that will write all logs matching the // given criteria to the given logs channel. -func (es *EventSystem) subscribeLogs(crit filters.FilterCriteria) (*Subscription, pubsub.UnsubscribeFunc, error) { +func (es *EventSystem) subscribeLogs(crit filters.FilterCriteria) (*Subscription, context.CancelFunc, error) { sub := &Subscription{ id: rpc.NewID(), typ: filters.LogsSubscription, @@ -184,17 +286,34 @@ func (es *EventSystem) subscribeLogs(crit filters.FilterCriteria) (*Subscription installed: make(chan struct{}, 1), err: make(chan error, 1), } + es.logger.Debug("\x1b[32m------ logs subscribe: %+v\x1b[0m\n", sub) + return es.subscribe(sub) +} + +// subscribeMinedPendingLogs creates a subscription that returned mined and +// pending logs that match the given criteria. +func (es *EventSystem) subscribeMinedPendingLogs(crit filters.FilterCriteria) (*Subscription, context.CancelFunc, error) { + sub := &Subscription{ + id: rpc.NewID(), + typ: filters.MinedAndPendingLogsSubscription, + event: evmEvents, + logsCrit: crit, + created: time.Now().UTC(), + logs: make(chan []*ethtypes.Log), + installed: make(chan struct{}, 1), + err: make(chan error, 1), + } return es.subscribe(sub) } // SubscribeNewHeads subscribes to new block headers events. -func (es EventSystem) SubscribeNewHeads() (*Subscription, pubsub.UnsubscribeFunc, error) { +func (es EventSystem) SubscribeNewHeads() (*Subscription, context.CancelFunc, error) { sub := &Subscription{ id: rpc.NewID(), typ: filters.BlocksSubscription, event: headerEvents, created: time.Now().UTC(), - headers: make(chan *ethtypes.Header), + headers: make(chan *types.Header), installed: make(chan struct{}, 1), err: make(chan error, 1), } @@ -202,7 +321,7 @@ func (es EventSystem) SubscribeNewHeads() (*Subscription, pubsub.UnsubscribeFunc } // SubscribePendingTxs subscribes to new pending transactions events from the mempool. -func (es EventSystem) SubscribePendingTxs() (*Subscription, pubsub.UnsubscribeFunc, error) { +func (es EventSystem) SubscribePendingTxs() (*Subscription, context.CancelFunc, error) { sub := &Subscription{ id: rpc.NewID(), typ: filters.PendingTransactionsSubscription, @@ -217,88 +336,138 @@ func (es EventSystem) SubscribePendingTxs() (*Subscription, pubsub.UnsubscribeFu type filterIndex map[filters.Type]map[rpc.ID]*Subscription -// eventLoop (un)installs filters and processes mux events. -func (es *EventSystem) eventLoop() { - for { - select { - case f := <-es.install: - es.indexMux.Lock() - es.index[f.typ][f.id] = f - ch := make(chan coretypes.ResultEvent) - es.topicChans[f.event] = ch - if err := es.eventBus.AddTopic(f.event, ch); err != nil { - es.logger.Error("failed to add event topic to event bus", "topic", f.event, "error", err.Error()) - } - es.indexMux.Unlock() - close(f.installed) - case f := <-es.uninstall: - es.indexMux.Lock() - delete(es.index[f.typ], f.id) - - var channelInUse bool - for _, sub := range es.index[f.typ] { - if sub.event == f.event { - channelInUse = true - break - } - } +func (es *EventSystem) handleLogs(ev coretypes.ResultEvent) { + data, _ := ev.Data.(tmtypes.EventDataTx) + es.logger.Debug("\x1b[32m------ logs data: %+v\x1b[0m\n", data) + // logReceipt := onetypes.GetTxEthLogs(&data.TxResult.Result, data.Index) + resultData, err := evmtypes.DecodeTransactionLogs(data.TxResult.Result.Data) + if err != nil { + return + } - // remove topic only when channel is not used by other subscriptions - if !channelInUse { - if err := es.tmWSClient.Unsubscribe(es.ctx, f.event); err != nil { - es.logger.Error("failed to unsubscribe from query", "query", f.event, "error", err.Error()) - } + if len(resultData.Logs) == 0 { + return + } - ch, ok := es.topicChans[f.event] - if ok { - es.eventBus.RemoveTopic(f.event) - close(ch) - delete(es.topicChans, f.event) - } - } + for _, f := range es.index[filters.LogsSubscription] { + matchedLogs := FilterLogs(evmtypes.LogsToEthereum(resultData.Logs), f.logsCrit.FromBlock, f.logsCrit.ToBlock, f.logsCrit.Addresses, f.logsCrit.Topics) + if len(matchedLogs) > 0 { + f.logs <- matchedLogs + } + } +} - es.indexMux.Unlock() - close(f.err) +func (es *EventSystem) handleTxsEvent(ev coretypes.ResultEvent) { + data, _ := ev.Data.(tmtypes.EventDataTx) + for _, f := range es.index[filters.PendingTransactionsSubscription] { + // NOTE: In previous version, data.Tx return types.Tx, but right now just bytes, + // so we need manually covert in order to get sha256 hash fot tx payload. + txHash, err := types.GetTxHash(es.clientCtx.TxConfig.TxDecoder(), tmtypes.Tx(data.Tx)) + if err != nil { + continue } + f.hashes <- []common.Hash{txHash} } } -func (es *EventSystem) consumeEvents() { - for { - for rpcResp := range es.tmWSClient.ResponsesCh { - var ev coretypes.ResultEvent - - if rpcResp.Error != nil { - time.Sleep(5 * time.Second) - continue - } else if err := tmjson.Unmarshal(rpcResp.Result, &ev); err != nil { - es.logger.Error("failed to JSON unmarshal ResponsesCh result event", "error", err.Error()) - continue - } +func (es *EventSystem) handleChainEvent(ev coretypes.ResultEvent) { + data, _ := ev.Data.(tmtypes.EventDataNewBlockHeader) + for _, f := range es.index[filters.BlocksSubscription] { + header, err := types.EthHeaderFromTendermint(data.Header) + if err != nil { + continue + } + f.headers <- header + } +} - if len(ev.Query) == 0 { - // skip empty responses - continue - } +// eventLoop (un)installs filters and processes mux events. +func (es *EventSystem) eventLoop() { + var ( + err error + cancelPendingTxsSubs, cancelLogsSubs, cancelPendingLogsSubs, cancelHeaderSubs context.CancelFunc + ) + + // Subscribe events + es.txsSub, cancelPendingTxsSubs, err = es.SubscribePendingTxs() + if err != nil { + panic(fmt.Errorf("failed to subscribe pending txs: %w", err)) + } + + defer cancelPendingTxsSubs() + + es.logsSub, cancelLogsSubs, err = es.SubscribeLogs(filters.FilterCriteria{}) + if err != nil { + panic(fmt.Errorf("failed to subscribe logs: %w", err)) + } + + defer cancelLogsSubs() + + es.pendingLogsSub, cancelPendingLogsSubs, err = es.subscribePendingLogs(filters.FilterCriteria{}) + if err != nil { + panic(fmt.Errorf("failed to subscribe pending logs: %w", err)) + } + + defer cancelPendingLogsSubs() + + es.chainSub, cancelHeaderSubs, err = es.SubscribeNewHeads() + if err != nil { + panic(fmt.Errorf("failed to subscribe headers: %w", err)) + } + + defer cancelHeaderSubs() - es.indexMux.RLock() - ch, ok := es.topicChans[ev.Query] - es.indexMux.RUnlock() - if !ok { - es.logger.Debug("channel for subscription not found", "topic", ev.Query) - es.logger.Debug("list of available channels", "channels", es.eventBus.Topics()) - continue + // Ensure all subscriptions get cleaned up + defer func() { + es.txsSub.Unsubscribe(es) + es.logsSub.Unsubscribe(es) + es.pendingLogsSub.Unsubscribe(es) + es.chainSub.Unsubscribe(es) + }() + + for { + select { + case txEvent := <-es.txsSub.eventCh: + es.logger.Debug("\x1b[32m------ tx event trigger from event loop: %+v\x1b[0m\n", txEvent) + es.handleTxsEvent(txEvent) + case headerEv := <-es.chainSub.eventCh: + es.logger.Debug("\x1b[32m------ header event trigger from event loop: %+v\x1b[0m\n", headerEv) + es.handleChainEvent(headerEv) + case logsEv := <-es.logsSub.eventCh: + es.logger.Debug("\x1b[32m------ logs event trigger from event loop: %+v\x1b[0m\n", logsEv) + es.handleLogs(logsEv) + case logsEv := <-es.pendingLogsSub.eventCh: + es.logger.Debug("\x1b[32m------ pending logs event trigger from event loop: %+v\x1b[0m\n", logsEv) + es.handleLogs(logsEv) + + case f := <-es.install: + if f.typ == filters.MinedAndPendingLogsSubscription { + // the type are logs and pending logs subscriptions + es.index[filters.LogsSubscription][f.id] = f + es.index[filters.PendingLogsSubscription][f.id] = f + } else { + es.index[f.typ][f.id] = f } + close(f.installed) - // gracefully handle lagging subscribers - t := time.NewTimer(time.Second) - select { - case <-t.C: - es.logger.Debug("dropped event during lagging subscription", "topic", ev.Query) - case ch <- ev: + case f := <-es.uninstall: + if f.typ == filters.MinedAndPendingLogsSubscription { + // the type are logs and pending logs subscriptions + delete(es.index[filters.LogsSubscription], f.id) + delete(es.index[filters.PendingLogsSubscription], f.id) + } else { + delete(es.index[f.typ], f.id) } + close(f.err) + // System stopped + case <-es.txsSub.Err(): + return + case <-es.logsSub.Err(): + return + case <-es.pendingLogsSub.Err(): + return + case <-es.chainSub.Err(): + return } - - time.Sleep(time.Second) } } diff --git a/rpc/namespaces/ethereum/eth/filters/filters.go b/rpc/namespaces/ethereum/eth/filters/filters.go index 1b6cb647..98faa945 100644 --- a/rpc/namespaces/ethereum/eth/filters/filters.go +++ b/rpc/namespaces/ethereum/eth/filters/filters.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/filters" + "github.com/stratosnet/stratos-chain/rpc/backend" "github.com/stratosnet/stratos-chain/rpc/types" ) @@ -26,7 +27,7 @@ type BloomIV struct { // Filter can be used to retrieve and filter logs. type Filter struct { logger log.Logger - backend Backend + backend backend.BackendI criteria filters.FilterCriteria bloomFilters [][]BloomIV // Filter the system is matching for @@ -34,14 +35,14 @@ type Filter struct { // NewBlockFilter creates a new filter which directly inspects the contents of // a block to figure out whether it is interesting or not. -func NewBlockFilter(logger log.Logger, backend Backend, criteria filters.FilterCriteria) *Filter { +func NewBlockFilter(logger log.Logger, b backend.BackendI, criteria filters.FilterCriteria) *Filter { // Create a generic filter and convert it into a block filter - return newFilter(logger, backend, criteria, nil) + return newFilter(logger, b, criteria, nil) } // NewRangeFilter creates a new filter which uses a bloom filter on blocks to // figure out whether a particular block is interesting or not. -func NewRangeFilter(logger log.Logger, backend Backend, begin, end int64, addresses []common.Address, topics [][]common.Hash) *Filter { +func NewRangeFilter(logger log.Logger, b backend.BackendI, begin, end int64, addresses []common.Address, topics [][]common.Hash) *Filter { // Flatten the address and topic filter clauses into a single bloombits filter // system. Since the bloombits are not positional, nil topics are permitted, // which get flattened into a nil byte slice. @@ -70,14 +71,14 @@ func NewRangeFilter(logger log.Logger, backend Backend, begin, end int64, addres Topics: topics, } - return newFilter(logger, backend, criteria, createBloomFilters(filtersBz, logger)) + return newFilter(logger, b, criteria, createBloomFilters(filtersBz, logger)) } // newFilter returns a new Filter -func newFilter(logger log.Logger, backend Backend, criteria filters.FilterCriteria, bloomFilters [][]BloomIV) *Filter { +func newFilter(logger log.Logger, b backend.BackendI, criteria filters.FilterCriteria, bloomFilters [][]BloomIV) *Filter { return &Filter{ logger: logger, - backend: backend, + backend: b, criteria: criteria, bloomFilters: bloomFilters, } diff --git a/rpc/namespaces/ethereum/eth/filters/subscription.go b/rpc/namespaces/ethereum/eth/filters/subscription.go index d9b22798..288dac60 100644 --- a/rpc/namespaces/ethereum/eth/filters/subscription.go +++ b/rpc/namespaces/ethereum/eth/filters/subscription.go @@ -3,6 +3,7 @@ package filters import ( "time" + "github.com/stratosnet/stratos-chain/rpc/types" coretypes "github.com/tendermint/tendermint/rpc/core/types" "github.com/ethereum/go-ethereum/common" @@ -20,7 +21,7 @@ type Subscription struct { logsCrit filters.FilterCriteria logs chan []*ethtypes.Log hashes chan []common.Hash - headers chan *ethtypes.Header + headers chan *types.Header installed chan struct{} // closed when the filter is installed eventCh <-chan coretypes.ResultEvent err chan error diff --git a/rpc/namespaces/ethereum/miner/api.go b/rpc/namespaces/ethereum/miner/api.go index 0e89d33d..59084403 100644 --- a/rpc/namespaces/ethereum/miner/api.go +++ b/rpc/namespaces/ethereum/miner/api.go @@ -104,7 +104,7 @@ func (api *API) SetEtherbase(etherbase common.Address) bool { WithChainID(api.clientCtx.ChainID). WithKeybase(api.clientCtx.Keyring). WithTxConfig(api.clientCtx.TxConfig). - WithSequence(uint64(*nonce)). + WithSequence(uint64(nonce)). WithGasAdjustment(1.25) _, gas, err := tx.CalculateGas(api.clientCtx, txFactory, msg) diff --git a/rpc/namespaces/ethereum/net/api.go b/rpc/namespaces/ethereum/net/api.go index 40a908f8..6cc61677 100644 --- a/rpc/namespaces/ethereum/net/api.go +++ b/rpc/namespaces/ethereum/net/api.go @@ -1,55 +1,37 @@ package net import ( - "context" - "fmt" "math/big" - rpcclient "github.com/tendermint/tendermint/rpc/client" - - "github.com/cosmos/cosmos-sdk/client" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stratosnet/stratos-chain/rpc/backend" ) // PublicAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec. type PublicAPI struct { - networkVersion uint64 - tmClient rpcclient.Client + backend backend.BackendI } // NewPublicAPI creates an instance of the public Net Web3 API. -func NewPublicAPI(clientCtx client.Context) *PublicAPI { - eip155ChainId, ok := new(big.Int).SetString(clientCtx.ChainID, 10) - if !ok { - panic("failed to parse chainID") - } - +func NewPublicAPI(backend backend.BackendI) *PublicAPI { return &PublicAPI{ - networkVersion: eip155ChainId.Uint64(), - tmClient: clientCtx.Client, + backend: backend, } } // Version returns the current ethereum protocol version. -func (s *PublicAPI) Version() string { - return fmt.Sprintf("%d", s.networkVersion) +func (s *PublicAPI) Version() (string, error) { + ctx := s.backend.GetSdkContext() + params := s.backend.GetEVMKeeper().GetParams(ctx) + return params.ChainConfig.ChainID.String(), nil } // Listening returns if client is actively listening for network connections. func (s *PublicAPI) Listening() bool { - ctx := context.Background() - netInfo, err := s.tmClient.NetInfo(ctx) - if err != nil { - return false - } - return netInfo.Listening + return s.backend.GetNode().IsListening() } // PeerCount returns the number of peers currently connected to the client. -func (s *PublicAPI) PeerCount() int { - ctx := context.Background() - netInfo, err := s.tmClient.NetInfo(ctx) - if err != nil { - return 0 - } - return len(netInfo.Peers) +func (s *PublicAPI) PeerCount() hexutil.Big { + return hexutil.Big(*big.NewInt(int64(len(s.backend.GetSwitch().Peers().List())))) } diff --git a/rpc/namespaces/ethereum/txpool/api.go b/rpc/namespaces/ethereum/txpool/api.go index 48e49dfb..ea1dd0a7 100644 --- a/rpc/namespaces/ethereum/txpool/api.go +++ b/rpc/namespaces/ethereum/txpool/api.go @@ -1,50 +1,90 @@ package txpool import ( + "fmt" + "github.com/tendermint/tendermint/libs/log" + "github.com/cosmos/cosmos-sdk/client" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stratosnet/stratos-chain/rpc/backend" "github.com/stratosnet/stratos-chain/rpc/types" ) // PublicAPI offers and API for the transaction pool. It only operates on data that is non-confidential. type PublicAPI struct { - logger log.Logger + logger log.Logger + clientCtx client.Context + backend backend.BackendI } // NewPublicAPI creates a new tx pool service that gives information about the transaction pool. -func NewPublicAPI(logger log.Logger) *PublicAPI { +func NewPublicAPI(logger log.Logger, clientCtx client.Context, backend backend.BackendI) *PublicAPI { return &PublicAPI{ - logger: logger.With("module", "txpool"), + logger: logger.With("module", "txpool"), + clientCtx: clientCtx, + backend: backend, + } +} + +func (api *PublicAPI) getPendingList() map[common.Address]map[string]*types.Transaction { + pTxs := types.GetPendingTxs(api.clientCtx.TxConfig.TxDecoder(), api.backend.GetMempool()) + pending := make(map[common.Address]map[string]*types.Transaction) + for _, pTx := range pTxs { + addrMap, ok := pending[pTx.From] + if !ok { + addrMap = make(map[string]*types.Transaction) + pending[pTx.From] = addrMap + } + addrMap[fmt.Sprintf("%d", pTx.Nonce)] = pTx } + return pending } // Content returns the transactions contained within the transaction pool -func (api *PublicAPI) Content() (map[string]map[string]map[string]*types.RPCTransaction, error) { +func (api *PublicAPI) Content() map[string]map[common.Address]map[string]*types.Transaction { api.logger.Debug("txpool_content") - content := map[string]map[string]map[string]*types.RPCTransaction{ - "pending": make(map[string]map[string]*types.RPCTransaction), - "queued": make(map[string]map[string]*types.RPCTransaction), + content := map[string]map[common.Address]map[string]*types.Transaction{ + "pending": api.getPendingList(), + "queued": make(map[common.Address]map[string]*types.Transaction), } - return content, nil + return content } // Inspect returns the content of the transaction pool and flattens it into an -func (api *PublicAPI) Inspect() (map[string]map[string]map[string]string, error) { +func (api *PublicAPI) Inspect() map[string]map[string]map[string]string { api.logger.Debug("txpool_inspect") content := map[string]map[string]map[string]string{ "pending": make(map[string]map[string]string), "queued": make(map[string]map[string]string), } - return content, nil + pending := api.getPendingList() + // Define a formatter to flatten a transaction into a string + var format = func(tx *types.Transaction) string { + if to := tx.To; to != nil { + return fmt.Sprintf("%s: %d wei + %d gas × %d wei", tx.To.Hex(), tx.Value.ToInt(), tx.Gas, tx.GasPrice.ToInt()) + } + return fmt.Sprintf("contract creation: %d wei + %d gas × %d wei", tx.Value.ToInt(), tx.Gas, tx.GasPrice.ToInt()) + } + // Flatten the pending transactions + for account, txs := range pending { + dump := make(map[string]string) + for _, tx := range txs { + dump[fmt.Sprintf("%d", tx.Nonce)] = format(tx) + } + content["pending"][account.Hex()] = dump + } + + return content } // Status returns the number of pending and queued transaction in the pool. func (api *PublicAPI) Status() map[string]hexutil.Uint { api.logger.Debug("txpool_status") return map[string]hexutil.Uint{ - "pending": hexutil.Uint(0), + "pending": hexutil.Uint(types.GetPendingTxsLen(api.backend.GetMempool())), "queued": hexutil.Uint(0), } } diff --git a/rpc/server.go b/rpc/server.go new file mode 100644 index 00000000..0c3f9fcd --- /dev/null +++ b/rpc/server.go @@ -0,0 +1,104 @@ +package rpc + +import ( + "context" + "net/http" + "time" + + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stratosnet/stratos-chain/server/config" + "github.com/tendermint/tendermint/libs/log" +) + +type Web3Server struct { + httpURI string + wsURI string + enabled bool + logger log.Logger +} + +func NewWeb3Server(cfg config.Config, logger log.Logger) *Web3Server { + return &Web3Server{ + httpURI: cfg.JSONRPC.Address, + wsURI: cfg.JSONRPC.WsAddress, + enabled: cfg.JSONRPC.Enable, + logger: logger, + } +} + +func (web3 *Web3Server) start(uri string, handler http.Handler) error { + if !web3.enabled { + web3.logger.Info("Web3 api disabled, skipping") + return nil + } + + var ( + err error + ) + channel := make(chan error) + timeout := make(chan error) + + srv := &http.Server{ + Addr: uri, + Handler: handler, + ReadTimeout: 60 * time.Second, + WriteTimeout: 60 * time.Second, + } + srv.SetKeepAlivesEnabled(true) + + //Timeout Go routine + go func() { + time.Sleep(time.Duration(2) * time.Second) + timeout <- nil + }() + + go func(ch chan error) { + web3.logger.Info("starting Web3 RPC server on " + uri) + err := srv.ListenAndServe() + if err != nil { + web3.logger.Error("server error, details: %s", err) + } + srv.Shutdown(context.TODO()) + ch <- err + }(channel) + + select { + case err = <-channel: + case err = <-timeout: + } + + return err +} + +func (web3 *Web3Server) registerAPIs(server *rpc.Server, apis []rpc.API) error { + for _, api := range apis { + if err := server.RegisterName(api.Namespace, api.Service); err != nil { + web3.logger.Error( + "failed to register service in JSON RPC namespace", + "namespace", api.Namespace, + "service", api.Service, + ) + return err + } + } + return nil +} + +func (web3 *Web3Server) StartHTTP(apis []rpc.API) error { + rpcSrv := rpc.NewServer() + handler := node.NewHTTPHandlerStack(rpcSrv, []string{"*"}, []string{"localhost", "host.docker.internal"}, []byte{}) // TODO: Replace cors and vshosts from config + if err := web3.registerAPIs(rpcSrv, apis); err != nil { + return err + } + return web3.start(web3.httpURI, handler) +} + +func (web3 *Web3Server) StartWS(apis []rpc.API) error { + rpcSrv := rpc.NewServer() + handler := rpcSrv.WebsocketHandler([]string{}) // TODO: Add config origins + if err := web3.registerAPIs(rpcSrv, apis); err != nil { + return err + } + return web3.start(web3.wsURI, handler) +} diff --git a/rpc/types/block.go b/rpc/types/block.go index 809505b3..a516f405 100644 --- a/rpc/types/block.go +++ b/rpc/types/block.go @@ -27,6 +27,7 @@ const ( EthPendingBlockNumber = BlockNumber(-2) EthLatestBlockNumber = BlockNumber(-1) EthEarliestBlockNumber = BlockNumber(0) + EthInitialBlockNumber = BlockNumber(1) ) const ( @@ -45,6 +46,7 @@ func NewBlockNumber(n *big.Int) BlockNumber { return BlockNumber(n.Int64()) } +// NOTE: Legacy, should be removed after cli rework // ContextWithHeight wraps a context with the a gRPC block height header. If the provided height is // 0, it will return an empty context and the gRPC query will use the latest block height for querying. // Note that all metadata are processed and removed by tendermint layer, so it wont be accessible at gRPC server level. diff --git a/rpc/types/query_client.go b/rpc/types/query_client.go index 1594a11d..57af7559 100644 --- a/rpc/types/query_client.go +++ b/rpc/types/query_client.go @@ -1,3 +1,4 @@ +// NOTE: Legacy!!! package types import ( @@ -14,9 +15,9 @@ import ( ) // QueryClient defines a gRPC Client used for: -// - Transaction simulation -// - EVM module queries -// - Fee market module queries +// - Transaction simulation +// - EVM module queries +// - Fee market module queries type QueryClient struct { tx.ServiceClient evmtypes.QueryClient diff --git a/rpc/types/types.go b/rpc/types/types.go index 9459cf8e..3ad20188 100644 --- a/rpc/types/types.go +++ b/rpc/types/types.go @@ -29,8 +29,8 @@ type StorageResult struct { Proof []string `json:"proof"` } -// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction -type RPCTransaction struct { +// Transaction represents a transaction that will serialize to the RPC representation of a transaction +type Transaction struct { BlockHash *common.Hash `json:"blockHash"` BlockNumber *hexutil.Big `json:"blockNumber"` From common.Address `json:"from"` @@ -87,3 +87,91 @@ type OneFeeHistory struct { Reward []*big.Int // each element of the array will have the tip provided to miners for the percentile given GasUsedRatio float64 // the ratio of gas used to the gas limit for each block } + +// NOTE: Forked because tendermint block hash calculated in another way +// default ethereum take rlp from the struct +type Header struct { + Hash common.Hash `json:"hash" gencodec:"required"` + ParentHash common.Hash `json:"parentHash" gencodec:"required"` + UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` + Coinbase common.Address `json:"miner" gencodec:"required"` + Root common.Hash `json:"stateRoot" gencodec:"required"` + TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` + ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` + Bloom ethtypes.Bloom `json:"logsBloom" gencodec:"required"` + Difficulty *big.Int `json:"difficulty" gencodec:"required"` + Number *big.Int `json:"number" gencodec:"required"` + GasLimit uint64 `json:"gasLimit" gencodec:"required"` + GasUsed uint64 `json:"gasUsed" gencodec:"required"` + Time uint64 `json:"timestamp" gencodec:"required"` + Extra []byte `json:"extraData" gencodec:"required"` + MixDigest common.Hash `json:"mixHash"` + Nonce ethtypes.BlockNonce `json:"nonce"` + Size uint64 `json:"size"` + + // BaseFee was added by EIP-1559 and is ignored in legacy headers. + // TODO: Add support + // NOTE: Do we need this in real? + // BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"` +} + +// Block represents a block returned to RPC clients. +type Block struct { + Number hexutil.Uint64 `json:"number"` + Hash common.Hash `json:"hash"` + ParentHash common.Hash `json:"parentHash"` + Nonce ethtypes.BlockNonce `json:"nonce"` + Sha3Uncles common.Hash `json:"sha3Uncles"` + LogsBloom ethtypes.Bloom `json:"logsBloom"` + TransactionsRoot common.Hash `json:"transactionsRoot"` + StateRoot common.Hash `json:"stateRoot"` + Miner common.Address `json:"miner"` + MixHash common.Hash `json:"mixHash"` + Difficulty hexutil.Uint64 `json:"difficulty"` + TotalDifficulty hexutil.Uint64 `json:"totalDifficulty"` + ExtraData hexutil.Bytes `json:"extraData"` + Size hexutil.Uint64 `json:"size"` + GasLimit *hexutil.Big `json:"gasLimit"` + GasUsed *hexutil.Big `json:"gasUsed"` + Timestamp hexutil.Uint64 `json:"timestamp"` + Uncles []common.Hash `json:"uncles"` + ReceiptsRoot common.Hash `json:"receiptsRoot"` + Transactions []interface{} `json:"transactions"` +} + +// TransactionReceipt represents a mined transaction returned to RPC clients. +type TransactionReceipt struct { + // Consensus fields: These fields are defined by the Yellow Paper + Status hexutil.Uint64 `json:"status"` + CumulativeGasUsed hexutil.Uint64 `json:"cumulativeGasUsed"` + LogsBloom ethtypes.Bloom `json:"logsBloom"` + Logs []*ethtypes.Log `json:"logs"` + + // Implementation fields: These fields are added by geth when processing a transaction. + // They are stored in the chain database. + TransactionHash common.Hash `json:"transactionHash"` + ContractAddress *common.Address `json:"contractAddress"` + GasUsed hexutil.Uint64 `json:"gasUsed"` + + // Inclusion information: These fields provide information about the inclusion of the + // transaction corresponding to this receipt. + BlockHash common.Hash `json:"blockHash"` + BlockNumber hexutil.Big `json:"blockNumber"` + TransactionIndex hexutil.Uint64 `json:"transactionIndex"` + + // sender and receiver (contract or EOA) addresses + From common.Address `json:"from"` + To *common.Address `json:"to"` +} + +type TxByNonce []*Transaction + +func (s TxByNonce) Len() int { return len(s) } +func (s TxByNonce) Less(i, j int) bool { return s[i].Nonce < s[j].Nonce } +func (s TxByNonce) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// Transactions implements DerivableList for transactions. +type Transactions []*Transaction + +// Len returns the length of s. +func (s Transactions) Len() int { return len(s) } diff --git a/rpc/types/utils.go b/rpc/types/utils.go index 21dfb729..007686f0 100644 --- a/rpc/types/utils.go +++ b/rpc/types/utils.go @@ -2,26 +2,53 @@ package types import ( "bytes" - "context" + "crypto/sha1" "encoding/hex" + "errors" "fmt" "math/big" + "sort" "strconv" + "github.com/cosmos/cosmos-sdk/client" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/mempool" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmtypes "github.com/tendermint/tendermint/types" - "github.com/cosmos/cosmos-sdk/client" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" ethtypes "github.com/ethereum/go-ethereum/core/types" - + stratos "github.com/stratosnet/stratos-chain/types" evmtypes "github.com/stratosnet/stratos-chain/x/evm/types" + "github.com/tendermint/tendermint/proto/tendermint/crypto" + tmrpccore "github.com/tendermint/tendermint/rpc/core" + tmrpccoretypes "github.com/tendermint/tendermint/rpc/core/types" ) +var bAttributeKeyEthereumBloom = []byte(evmtypes.AttributeKeyEthereumBloom) +var MempoolCapacity = 100 + +// HashToUint64 used to convert string or hash string to uint64 +func HashToUint64(s string) uint64 { + h := sha1.New() + h.Write([]byte(s)) + + hash := h.Sum(nil)[:2] + result := uint64(0) + for i := 0; i < len(hash); i++ { + result = result << 8 + result += uint64(hash[i]) + + } + return result +} + // RawTxToEthTx returns a evm MsgEthereum transaction from raw tx bytes. func RawTxToEthTx(clientCtx client.Context, txBz tmtypes.Tx) ([]*evmtypes.MsgEthereumTx, error) { tx, err := clientCtx.TxConfig.TxDecoder()(txBz) @@ -40,37 +67,116 @@ func RawTxToEthTx(clientCtx client.Context, txBz tmtypes.Tx) ([]*evmtypes.MsgEth return ethTxs, nil } +func GetBlockBloom(blockResults *tmrpccoretypes.ResultBlockResults) (ethtypes.Bloom, error) { + for _, event := range blockResults.EndBlockEvents { + if event.Type != evmtypes.EventTypeBlockBloom { + continue + } + + for _, attr := range event.Attributes { + if bytes.Equal(attr.Key, bAttributeKeyEthereumBloom) { + return ethtypes.BytesToBloom(attr.Value), nil + } + } + } + return ethtypes.Bloom{}, errors.New("block bloom event is not found") +} + // EthHeaderFromTendermint is an util function that returns an Ethereum Header // from a tendermint Header. -func EthHeaderFromTendermint(header tmtypes.Header, bloom ethtypes.Bloom, baseFee *big.Int) *ethtypes.Header { - txHash := ethtypes.EmptyRootHash - if len(header.DataHash) == 0 { - txHash = common.BytesToHash(header.DataHash) +func EthHeaderFromTendermint(header tmtypes.Header) (*Header, error) { + results, err := tmrpccore.BlockResults(nil, &header.Height) + if err != nil { + return nil, err + } + gasLimit, err := BlockMaxGasFromConsensusParams(header.Height) + if err != nil { + return nil, err + } + + bloom, err := GetBlockBloom(results) + if err != nil { + return nil, err + } + + gasUsed := int64(0) + for _, txResult := range results.TxsResults { + gasUsed += txResult.GasUsed } - return ðtypes.Header{ - ParentHash: common.BytesToHash(header.LastBlockID.Hash.Bytes()), - UncleHash: ethtypes.EmptyUncleHash, + return &Header{ + Hash: common.BytesToHash(header.Hash()), + ParentHash: common.BytesToHash(header.LastBlockID.Hash), + UncleHash: common.Hash{}, Coinbase: common.BytesToAddress(header.ProposerAddress), Root: common.BytesToHash(header.AppHash), - TxHash: txHash, - ReceiptHash: ethtypes.EmptyRootHash, + TxHash: common.BytesToHash(header.DataHash), + ReceiptHash: common.Hash{}, Bloom: bloom, - Difficulty: big.NewInt(0), + Difficulty: big.NewInt(1), // NOTE: Maybe move to some constant? Number: big.NewInt(header.Height), - GasLimit: 0, - GasUsed: 0, - Time: uint64(header.Time.UTC().Unix()), - Extra: []byte{}, + GasLimit: uint64(gasLimit), + GasUsed: uint64(gasUsed), + Time: uint64(header.Time.Unix()), + Extra: common.Hex2Bytes(""), MixDigest: common.Hash{}, Nonce: ethtypes.BlockNonce{}, - BaseFee: baseFee, + // TODO: Add size somehow for legacy subscription support as for a new Header type after London + // is not exist but still present in newBlockHeaders call on subscription + }, nil +} + +// EthBlockFromTendermint returns a JSON-RPC compatible Ethereum blockfrom a given Tendermint block. +func EthBlockFromTendermint(txDecoder sdk.TxDecoder, block *tmtypes.Block, fullTx bool) (*Block, error) { + header, err := EthHeaderFromTendermint(block.Header) + if err != nil { + return nil, err } + + transactions := make([]interface{}, 0, len(block.Txs)) + for i, tmTx := range block.Txs { + if !fullTx { + transactions = append(transactions, common.Bytes2Hex(tmTx.Hash())) + continue + } + blockHash := common.BytesToHash(block.Hash()) + blockHeight := uint64(block.Height) + txIndex := uint64(i) + tx, err := TmTxToEthTx(txDecoder, tmTx, &blockHash, &blockHeight, &txIndex) + if err != nil { + // NOTE: Add debug? + continue + } + transactions = append(transactions, tx) + } + + return &Block{ + Number: hexutil.Uint64(header.Number.Uint64()), + Hash: header.Hash, + ParentHash: header.ParentHash, + Nonce: ethtypes.BlockNonce{}, // PoW specific + Sha3Uncles: common.Hash{}, // No uncles in Tendermint + LogsBloom: header.Bloom, + TransactionsRoot: header.TxHash, + StateRoot: header.Root, + Miner: header.Coinbase, + MixHash: common.Hash{}, + Difficulty: hexutil.Uint64(header.Difficulty.Uint64()), + TotalDifficulty: hexutil.Uint64(header.Difficulty.Uint64()), + ExtraData: common.Hex2Bytes(""), + Size: hexutil.Uint64(block.Size()), + GasLimit: (*hexutil.Big)(new(big.Int).SetUint64(header.GasLimit)), + GasUsed: (*hexutil.Big)(new(big.Int).SetUint64(header.GasUsed)), + Timestamp: hexutil.Uint64(header.Time), + Transactions: transactions, + Uncles: make([]common.Hash, 0), + ReceiptsRoot: common.Hash{}, + }, nil } // BlockMaxGasFromConsensusParams returns the gas limit for the current block from the chain consensus params. -func BlockMaxGasFromConsensusParams(goCtx context.Context, clientCtx client.Context, blockHeight int64) (int64, error) { - resConsParams, err := clientCtx.Client.ConsensusParams(goCtx, &blockHeight) +func BlockMaxGasFromConsensusParams(blockHeight int64) (int64, error) { + resConsParams, err := tmrpccore.ConsensusParams(nil, &blockHeight) if err != nil { return int64(^uint32(0)), err } @@ -86,51 +192,6 @@ func BlockMaxGasFromConsensusParams(goCtx context.Context, clientCtx client.Cont return gasLimit, nil } -// FormatBlock creates an ethereum block from a tendermint header and ethereum-formatted -// transactions. -func FormatBlock( - header tmtypes.Header, size int, gasLimit int64, - gasUsed *big.Int, transactions []interface{}, bloom ethtypes.Bloom, - validatorAddr common.Address, baseFee *big.Int, -) map[string]interface{} { - var transactionsRoot common.Hash - if len(transactions) == 0 { - transactionsRoot = ethtypes.EmptyRootHash - } else { - transactionsRoot = common.BytesToHash(header.DataHash) - } - - result := map[string]interface{}{ - "number": hexutil.Uint64(header.Height), - "hash": hexutil.Bytes(header.Hash()), - "parentHash": common.BytesToHash(header.LastBlockID.Hash.Bytes()), - "nonce": ethtypes.BlockNonce{}, // PoW specific - "sha3Uncles": ethtypes.EmptyUncleHash, // No uncles in Tendermint - "logsBloom": bloom, - "stateRoot": hexutil.Bytes(header.AppHash), - "miner": validatorAddr, - "mixHash": common.Hash{}, - "difficulty": (*hexutil.Big)(big.NewInt(0)), - "extraData": "0x", - "size": hexutil.Uint64(size), - "gasLimit": hexutil.Uint64(gasLimit), // Static gas limit - "gasUsed": (*hexutil.Big)(gasUsed), - "timestamp": hexutil.Uint64(header.Time.Unix()), - "transactionsRoot": transactionsRoot, - "receiptsRoot": ethtypes.EmptyRootHash, - - "uncles": []common.Hash{}, - "transactions": transactions, - "totalDifficulty": (*hexutil.Big)(big.NewInt(0)), - } - - if baseFee != nil { - result["baseFeePerGas"] = (*hexutil.Big)(baseFee) - } - - return result -} - type DataError interface { Error() string // returns the message ErrorData() interface{} // returns the error data @@ -162,23 +223,230 @@ func ErrRevertedWith(data []byte) DataError { } } -// NewTransactionFromMsg returns a transaction that will serialize to the RPC -// representation, with the given location metadata set (if available). -func NewTransactionFromMsg( - msg *evmtypes.MsgEthereumTx, - blockHash common.Hash, - blockNumber, index uint64, - baseFee *big.Int, -) (*RPCTransaction, error) { - tx := msg.AsTransaction() - return NewRPCTransaction(tx, blockHash, blockNumber, index, baseFee) +// GetPendingTxCountByAddress is used to get pending tx count (nonce) for user address +func GetPendingTxCountByAddress(txDecoder sdk.TxDecoder, mem mempool.Mempool, address common.Address) (total uint64) { + for _, tmTx := range mem.ReapMaxTxs(MempoolCapacity) { + tx, err := txDecoder(tmTx) + if err != nil { + continue + } + msg := tx.GetMsgs()[0] + if ethMsg, ok := msg.(*evmtypes.MsgEthereumTx); ok { + ethTx := ethMsg.AsTransaction() + var signer ethtypes.Signer + if ethTx.Protected() { + signer = ethtypes.LatestSignerForChainID(ethTx.ChainId()) + } else { + signer = ethtypes.HomesteadSigner{} + } + from, _ := ethtypes.Sender(signer, ethTx) + if bytes.Equal(from.Bytes(), address.Bytes()) { + total++ + } + } + } + return +} + +// GetProof performs an ABCI query with the given key and returns a merkle proof. The desired +// tendermint height to perform the query should be set in the client context. The query will be +// performed at one below this height (at the IAVL version) in order to obtain the correct merkle +// proof. Proof queries at height less than or equal to 2 are not supported. +// Issue: https://github.com/cosmos/cosmos-sdk/issues/6567 +func GetProof(height int64, storeKey string, key []byte) ([]byte, *crypto.ProofOps, error) { + // ABCI queries at height less than or equal to 2 are not supported. + // Base app does not support queries for height less than or equal to 1. + // Therefore, a query at height 2 would be equivalent to a query at height 3 + if height <= 2 { + return nil, nil, fmt.Errorf("proof queries at height <= 2 are not supported") + } + + // Use the IAVL height if a valid tendermint height is passed in. + height-- + + abciRes, err := tmrpccore.ABCIQuery(nil, fmt.Sprintf("store/%s/key", storeKey), key, height, true) + if err != nil { + return nil, nil, err + } + + return abciRes.Response.Value, abciRes.Response.ProofOps, nil +} + +func FormatTmHeaderToProto(header *tmtypes.Header) tmproto.Header { + return tmproto.Header{ + Version: header.Version, + ChainID: header.ChainID, + Height: header.Height, + Time: header.Time, + LastBlockId: tmproto.BlockID{ + Hash: header.LastBlockID.Hash, + PartSetHeader: tmproto.PartSetHeader{ + Total: header.LastBlockID.PartSetHeader.Total, + Hash: header.LastBlockID.PartSetHeader.Hash, + }, + }, + LastCommitHash: header.LastCommitHash, + DataHash: header.DataHash, + ValidatorsHash: header.ValidatorsHash, + NextValidatorsHash: header.NextValidatorsHash, + ConsensusHash: header.ConsensusHash, + AppHash: header.AppHash, + LastResultsHash: header.LastResultsHash, + EvidenceHash: header.EvidenceHash, + ProposerAddress: header.ProposerAddress, + } +} + +// GetBlockCumulativeGas returns the cumulative gas used on a block up to a given +// transaction index. The returned gas used includes the gas from both the SDK and +// EVM module transactions. +func GetBlockCumulativeGas(blockResults *tmrpccoretypes.ResultBlockResults, idx int) uint64 { + var gasUsed uint64 + + for i := 0; i < idx && i < len(blockResults.TxsResults); i++ { + tx := blockResults.TxsResults[i] + gasUsed += uint64(tx.GasUsed) + } + return gasUsed +} + +func GetPendingTx(txDecoder sdk.TxDecoder, mem mempool.Mempool, hash common.Hash) (*Transaction, error) { + for _, uTx := range mem.ReapMaxTxs(MempoolCapacity) { + if bytes.Equal(uTx.Hash(), hash.Bytes()) { + return TmTxToEthTx(txDecoder, uTx, nil, nil, nil) + } + } + return nil, nil +} + +func GetPendingTxs(txDecoder sdk.TxDecoder, mem mempool.Mempool) []*Transaction { + txs := make([]*Transaction, 0, MempoolCapacity) + for _, uTx := range mem.ReapMaxTxs(MempoolCapacity) { + if tx, err := TmTxToEthTx(txDecoder, uTx, nil, nil, nil); err == nil { + txs = append(txs, tx) + } + } + sort.Sort(TxByNonce(txs)) + return txs +} + +func GetPendingTxsLen(mem mempool.Mempool) int { + return len(mem.ReapMaxTxs(MempoolCapacity)) +} + +func GetNonEVMSignatures(sig []byte) (v, r, s *big.Int) { + var tmpV byte + if len(sig) == 65 { + tmpV = sig[len(sig)-1:][0] + } else { + // in case of 64 length + tmpV = byte(int(sig[0]) % 2) + } + + v = new(big.Int).SetBytes([]byte{tmpV + 27}) + r = new(big.Int).SetBytes(sig[:32]) + s = new(big.Int).SetBytes(sig[32:64]) + return +} + +// GetTxHash get hash depends on what type, unfortunatelly system support two tx hash algo +// in order to have opportunity for off chain tx hash computation +func GetTxHash(txDecoder sdk.TxDecoder, tmTx tmtypes.Tx) (common.Hash, error) { + tx, err := txDecoder(tmTx) + if err != nil { + return common.Hash{}, err + } + if len(tx.GetMsgs()) == 0 { + return common.Hash{}, errors.New("tx contain empty msgs") + } + msg := tx.GetMsgs()[0] + if ethMsg, ok := msg.(*evmtypes.MsgEthereumTx); ok { + return ethMsg.AsTransaction().Hash(), nil + } else { + return common.BytesToHash(tmTx.Hash()), nil + } +} + +// TmTxToEthTx convert ethereum and rest transaction on ethereum based structure +func TmTxToEthTx( + txDecoder sdk.TxDecoder, + tmTx tmtypes.Tx, + blockHash *common.Hash, + blockNumber, index *uint64, +) (*Transaction, error) { + tx, err := txDecoder(tmTx) + if err != nil { + return nil, err + } + + // the `msgIndex` is inferred from tx events, should be within the bound. + // always taking first into account + msg := tx.GetMsgs()[0] + + if ethMsg, ok := msg.(*evmtypes.MsgEthereumTx); ok { + tx := ethMsg.AsTransaction() + return NewRPCTransaction(tx, blockHash, blockNumber, index) + } else { + addr := msg.GetSigners()[0] + from := common.BytesToAddress(addr.Bytes()) + + nonce := uint64(0) + v := new(big.Int).SetInt64(0) + r := new(big.Int).SetInt64(0) + s := new(big.Int).SetInt64(0) + sigTx, ok := tx.(authsigning.SigVerifiableTx) + if ok { + sigs, _ := sigTx.GetSignaturesV2() + if len(sigs) > 0 { + sig := sigs[0] + sigProto := signing.SignatureDataToProto(sig.Data) + v, r, s = GetNonEVMSignatures(sigProto.GetSingle().GetSignature()) + nonce = sig.Sequence + } + } else { + fmt.Printf("failed to get signature for %s\n", tmTx.Hash()) + } + + gas := uint64(0) + gasPrice := new(big.Int).SetInt64(stratos.DefaultGasPrice) + if feeTx, ok := tx.(sdk.FeeTx); ok { + gas = feeTx.GetGas() + gasPrice = new(big.Int).Div( + feeTx.GetFee().AmountOf("wei").BigInt(), // TODO: mv somehow wei from config + new(big.Int).SetUint64(gas), + ) + } + + var bNumber *big.Int + if blockNumber != nil { + bNumber = new(big.Int).SetUint64(*blockNumber) + } + + return &Transaction{ + BlockHash: blockHash, + BlockNumber: (*hexutil.Big)(bNumber), + Type: hexutil.Uint64(HashToUint64(sdk.MsgTypeURL(msg))), + From: from, + Gas: hexutil.Uint64(gas), + GasPrice: (*hexutil.Big)(gasPrice), + Hash: common.BytesToHash(tmTx.Hash()), + Input: make(hexutil.Bytes, 0), + Nonce: hexutil.Uint64(nonce), + To: new(common.Address), + TransactionIndex: (*hexutil.Uint64)(index), + Value: (*hexutil.Big)(new(big.Int).SetInt64(0)), // NOTE: How to get value in generic way? + V: (*hexutil.Big)(v), + R: (*hexutil.Big)(r), + S: (*hexutil.Big)(s), + }, nil + } } // NewTransactionFromData returns a transaction that will serialize to the RPC // representation, with the given location metadata set (if available). func NewRPCTransaction( - tx *ethtypes.Transaction, blockHash common.Hash, blockNumber, index uint64, baseFee *big.Int, -) (*RPCTransaction, error) { + tx *ethtypes.Transaction, blockHash *common.Hash, blockNumber, index *uint64, +) (*Transaction, error) { // Determine the signer. For replay-protected transactions, use the most permissive // signer, because we assume that signers are backwards-compatible with old // transactions. For non-protected transactions, the homestead signer signer is used @@ -191,7 +459,7 @@ func NewRPCTransaction( } from, _ := ethtypes.Sender(signer, tx) v, r, s := tx.RawSignatureValues() - result := &RPCTransaction{ + result := &Transaction{ Type: hexutil.Uint64(tx.Type()), From: from, Gas: hexutil.Uint64(tx.Gas()), @@ -205,10 +473,10 @@ func NewRPCTransaction( R: (*hexutil.Big)(r), S: (*hexutil.Big)(s), } - if blockHash != (common.Hash{}) { - result.BlockHash = &blockHash - result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber)) - result.TransactionIndex = (*hexutil.Uint64)(&index) + if blockHash != nil { + result.BlockHash = blockHash + result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(*blockNumber)) + result.TransactionIndex = (*hexutil.Uint64)(index) } switch tx.Type() { case ethtypes.AccessListTxType: @@ -221,14 +489,7 @@ func NewRPCTransaction( result.ChainID = (*hexutil.Big)(tx.ChainId()) result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap()) result.GasTipCap = (*hexutil.Big)(tx.GasTipCap()) - // if the transaction has been mined, compute the effective gas price - if baseFee != nil && blockHash != (common.Hash{}) { - // price = min(tip, gasFeeCap - baseFee) + baseFee - price := math.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee), tx.GasFeeCap()) - result.GasPrice = (*hexutil.Big)(price) - } else { - result.GasPrice = (*hexutil.Big)(tx.GasFeeCap()) - } + result.GasPrice = (*hexutil.Big)(tx.GasPrice()) } return result, nil } diff --git a/rpc/websockets.go b/rpc/websockets.go deleted file mode 100644 index 1bc2e73b..00000000 --- a/rpc/websockets.go +++ /dev/null @@ -1,659 +0,0 @@ -package rpc - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io/ioutil" - "math/big" - "net" - "net/http" - "sync" - - "github.com/gorilla/mux" - "github.com/gorilla/websocket" - "github.com/pkg/errors" - - "github.com/tendermint/tendermint/libs/log" - rpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client" - tmtypes "github.com/tendermint/tendermint/types" - - "github.com/cosmos/cosmos-sdk/client" - - "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/filters" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" - - "github.com/stratosnet/stratos-chain/rpc/ethereum/pubsub" - rpcfilters "github.com/stratosnet/stratos-chain/rpc/namespaces/ethereum/eth/filters" - "github.com/stratosnet/stratos-chain/rpc/types" - "github.com/stratosnet/stratos-chain/server/config" - evmtypes "github.com/stratosnet/stratos-chain/x/evm/types" -) - -type WebsocketsServer interface { - Start() -} - -type SubscriptionResponseJSON struct { - Jsonrpc string `json:"jsonrpc"` - Result interface{} `json:"result"` - ID float64 `json:"id"` -} - -type SubscriptionNotification struct { - Jsonrpc string `json:"jsonrpc"` - Method string `json:"method"` - Params *SubscriptionResult `json:"params"` -} - -type SubscriptionResult struct { - Subscription rpc.ID `json:"subscription"` - Result interface{} `json:"result"` -} - -type ErrorResponseJSON struct { - Jsonrpc string `json:"jsonrpc"` - Error *ErrorMessageJSON `json:"error"` - ID *big.Int `json:"id"` -} - -type ErrorMessageJSON struct { - Code *big.Int `json:"code"` - Message string `json:"message"` -} - -type websocketsServer struct { - rpcAddr string // listen address of rest-server - wsAddr string // listen address of ws server - certFile string - keyFile string - api *pubSubAPI - logger log.Logger -} - -func NewWebsocketsServer(clientCtx client.Context, logger log.Logger, tmWSClient *rpcclient.WSClient, cfg config.Config) WebsocketsServer { - logger = logger.With("api", "websocket-server") - _, port, _ := net.SplitHostPort(cfg.JSONRPC.Address) - - return &websocketsServer{ - rpcAddr: "localhost:" + port, // FIXME: this shouldn't be hardcoded to localhost - wsAddr: cfg.JSONRPC.WsAddress, - certFile: cfg.TLS.CertificatePath, - keyFile: cfg.TLS.KeyPath, - api: newPubSubAPI(clientCtx, logger, tmWSClient), - logger: logger, - } -} - -func (s *websocketsServer) Start() { - ws := mux.NewRouter() - ws.Handle("/", s) - - go func() { - var err error - if s.certFile == "" || s.keyFile == "" { - err = http.ListenAndServe(s.wsAddr, ws) - } else { - err = http.ListenAndServeTLS(s.wsAddr, s.certFile, s.keyFile, ws) - } - - if err != nil { - if err == http.ErrServerClosed { - return - } - - s.logger.Error("failed to start HTTP server for WS", "error", err.Error()) - } - }() -} - -func (s *websocketsServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { - upgrader := websocket.Upgrader{ - CheckOrigin: func(r *http.Request) bool { - return true - }, - } - - conn, err := upgrader.Upgrade(w, r, nil) - if err != nil { - s.logger.Debug("websocket upgrade failed", "error", err.Error()) - return - } - - s.readLoop(&wsConn{ - mux: new(sync.Mutex), - conn: conn, - }) -} - -func (s *websocketsServer) sendErrResponse(wsConn *wsConn, msg string) { - res := &ErrorResponseJSON{ - Jsonrpc: "2.0", - Error: &ErrorMessageJSON{ - Code: big.NewInt(-32600), - Message: msg, - }, - ID: nil, - } - - _ = wsConn.WriteJSON(res) -} - -type wsConn struct { - conn *websocket.Conn - mux *sync.Mutex -} - -func (w *wsConn) WriteJSON(v interface{}) error { - w.mux.Lock() - defer w.mux.Unlock() - - return w.conn.WriteJSON(v) -} - -func (w *wsConn) Close() error { - w.mux.Lock() - defer w.mux.Unlock() - - return w.conn.Close() -} - -func (w *wsConn) ReadMessage() (messageType int, p []byte, err error) { - // not protected by write mutex - - return w.conn.ReadMessage() -} - -func (s *websocketsServer) readLoop(wsConn *wsConn) { - // subscriptions of current connection - subscriptions := make(map[rpc.ID]pubsub.UnsubscribeFunc) - defer func() { - // cancel all subscriptions when connection closed - for _, unsubFn := range subscriptions { - unsubFn() - } - }() - - for { - _, mb, err := wsConn.ReadMessage() - if err != nil { - _ = wsConn.Close() - return - } - - var msg map[string]interface{} - if err = json.Unmarshal(mb, &msg); err != nil { - s.sendErrResponse(wsConn, err.Error()) - continue - } - - // check if method == eth_subscribe or eth_unsubscribe - method, ok := msg["method"].(string) - if !ok { - // otherwise, call the usual rpc server to respond - if err := s.tcpGetAndSendResponse(wsConn, mb); err != nil { - s.sendErrResponse(wsConn, err.Error()) - } - - continue - } - - connID, ok := msg["id"].(float64) - if !ok { - s.sendErrResponse( - wsConn, - fmt.Errorf("invalid type for connection ID: %T", msg["id"]).Error(), - ) - continue - } - - switch method { - case "eth_subscribe": - params, ok := msg["params"].([]interface{}) - if !ok { - s.sendErrResponse(wsConn, "invalid parameters") - continue - } - - if len(params) == 0 { - s.sendErrResponse(wsConn, "empty parameters") - continue - } - - subID := rpc.NewID() - unsubFn, err := s.api.subscribe(wsConn, subID, params) - if err != nil { - s.sendErrResponse(wsConn, err.Error()) - continue - } - subscriptions[subID] = unsubFn - - res := &SubscriptionResponseJSON{ - Jsonrpc: "2.0", - ID: connID, - Result: subID, - } - - if err := wsConn.WriteJSON(res); err != nil { - break - } - case "eth_unsubscribe": - params, ok := msg["params"].([]interface{}) - if !ok { - s.sendErrResponse(wsConn, "invalid parameters") - continue - } - - if len(params) == 0 { - s.sendErrResponse(wsConn, "empty parameters") - continue - } - - id, ok := params[0].(string) - if !ok { - s.sendErrResponse(wsConn, "invalid parameters") - continue - } - - subID := rpc.ID(id) - unsubFn, ok := subscriptions[subID] - if ok { - delete(subscriptions, subID) - unsubFn() - } - - res := &SubscriptionResponseJSON{ - Jsonrpc: "2.0", - ID: connID, - Result: ok, - } - - if err := wsConn.WriteJSON(res); err != nil { - break - } - default: - // otherwise, call the usual rpc server to respond - if err := s.tcpGetAndSendResponse(wsConn, mb); err != nil { - s.sendErrResponse(wsConn, err.Error()) - } - } - } -} - -// tcpGetAndSendResponse connects to the rest-server over tcp, posts a JSON-RPC request, and sends the response -// to the client over websockets -func (s *websocketsServer) tcpGetAndSendResponse(wsConn *wsConn, mb []byte) error { - req, err := http.NewRequestWithContext(context.Background(), "POST", "http://"+s.rpcAddr, bytes.NewBuffer(mb)) - if err != nil { - return errors.Wrap(err, "Could not build request") - } - - req.Header.Set("Content-Type", "application/json") - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - return errors.Wrap(err, "Could not perform request") - } - - defer resp.Body.Close() - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return errors.Wrap(err, "could not read body from response") - } - - var wsSend interface{} - err = json.Unmarshal(body, &wsSend) - if err != nil { - return errors.Wrap(err, "failed to unmarshal rest-server response") - } - - return wsConn.WriteJSON(wsSend) -} - -// pubSubAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec -type pubSubAPI struct { - events *rpcfilters.EventSystem - logger log.Logger - clientCtx client.Context -} - -// newPubSubAPI creates an instance of the ethereum PubSub API. -func newPubSubAPI(clientCtx client.Context, logger log.Logger, tmWSClient *rpcclient.WSClient) *pubSubAPI { - logger = logger.With("module", "websocket-client") - return &pubSubAPI{ - events: rpcfilters.NewEventSystem(logger, tmWSClient), - logger: logger, - clientCtx: clientCtx, - } -} - -func (api *pubSubAPI) subscribe(wsConn *wsConn, subID rpc.ID, params []interface{}) (pubsub.UnsubscribeFunc, error) { - method, ok := params[0].(string) - if !ok { - return nil, errors.New("invalid parameters") - } - - switch method { - case "newHeads": - // TODO: handle extra params - return api.subscribeNewHeads(wsConn, subID) - case "logs": - if len(params) > 1 { - return api.subscribeLogs(wsConn, subID, params[1]) - } - return api.subscribeLogs(wsConn, subID, nil) - case "newPendingTransactions": - return api.subscribePendingTransactions(wsConn, subID) - case "syncing": - return api.subscribeSyncing(wsConn, subID) - default: - return nil, errors.Errorf("unsupported method %s", method) - } -} - -func (api *pubSubAPI) subscribeNewHeads(wsConn *wsConn, subID rpc.ID) (pubsub.UnsubscribeFunc, error) { - sub, unsubFn, err := api.events.SubscribeNewHeads() - if err != nil { - return nil, errors.Wrap(err, "error creating block filter") - } - - // TODO: use events - baseFee := big.NewInt(params.InitialBaseFee) - - go func() { - headersCh := sub.Event() - errCh := sub.Err() - for { - select { - case event, ok := <-headersCh: - if !ok { - return - } - - data, ok := event.Data.(tmtypes.EventDataNewBlockHeader) - if !ok { - api.logger.Debug("event data type mismatch", "type", fmt.Sprintf("%T", event.Data)) - continue - } - - header := types.EthHeaderFromTendermint(data.Header, ethtypes.Bloom{}, baseFee) - - // write to ws conn - res := &SubscriptionNotification{ - Jsonrpc: "2.0", - Method: "eth_subscription", - Params: &SubscriptionResult{ - Subscription: subID, - Result: header, - }, - } - - err = wsConn.WriteJSON(res) - if err != nil { - api.logger.Error("error writing header, will drop peer", "error", err.Error()) - - try(func() { - if err != websocket.ErrCloseSent { - _ = wsConn.Close() - } - }, api.logger, "closing websocket peer sub") - } - case err, ok := <-errCh: - if !ok { - return - } - api.logger.Debug("dropping NewHeads WebSocket subscription", "subscription-id", subID, "error", err.Error()) - } - } - }() - - return unsubFn, nil -} - -func try(fn func(), l log.Logger, desc string) { - defer func() { - if x := recover(); x != nil { - if err, ok := x.(error); ok { - // debug.PrintStack() - l.Debug("panic during "+desc, "error", err.Error()) - return - } - - l.Debug(fmt.Sprintf("panic during %s: %+v", desc, x)) - return - } - }() - - fn() -} - -func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID rpc.ID, extra interface{}) (pubsub.UnsubscribeFunc, error) { - crit := filters.FilterCriteria{} - - if extra != nil { - params, ok := extra.(map[string]interface{}) - if !ok { - err := errors.New("invalid criteria") - api.logger.Debug("invalid criteria", "type", fmt.Sprintf("%T", extra)) - return nil, err - } - - if params["address"] != nil { - address, isString := params["address"].(string) - addresses, isSlice := params["address"].([]interface{}) - if !isString && !isSlice { - err := errors.New("invalid addresses; must be address or array of addresses") - api.logger.Debug("invalid addresses", "type", fmt.Sprintf("%T", params["address"])) - return nil, err - } - - if ok { - crit.Addresses = []common.Address{common.HexToAddress(address)} - } - - if isSlice { - crit.Addresses = []common.Address{} - for _, addr := range addresses { - address, ok := addr.(string) - if !ok { - err := errors.New("invalid address") - api.logger.Debug("invalid address", "type", fmt.Sprintf("%T", addr)) - return nil, err - } - - crit.Addresses = append(crit.Addresses, common.HexToAddress(address)) - } - } - } - - if params["topics"] != nil { - topics, ok := params["topics"].([]interface{}) - if !ok { - err := errors.Errorf("invalid topics: %s", topics) - api.logger.Error("invalid topics", "type", fmt.Sprintf("%T", topics)) - return nil, err - } - - crit.Topics = make([][]common.Hash, len(topics)) - - addCritTopic := func(topicIdx int, topic interface{}) error { - tstr, ok := topic.(string) - if !ok { - err := errors.Errorf("invalid topic: %s", topic) - api.logger.Error("invalid topic", "type", fmt.Sprintf("%T", topic)) - return err - } - - crit.Topics[topicIdx] = []common.Hash{common.HexToHash(tstr)} - return nil - } - - for topicIdx, subtopics := range topics { - if subtopics == nil { - continue - } - - // in case we don't have list, but a single topic value - if topic, ok := subtopics.(string); ok { - if err := addCritTopic(topicIdx, topic); err != nil { - return nil, err - } - - continue - } - - // in case we actually have a list of subtopics - subtopicsList, ok := subtopics.([]interface{}) - if !ok { - err := errors.New("invalid subtopics") - api.logger.Error("invalid subtopic", "type", fmt.Sprintf("%T", subtopics)) - return nil, err - } - - subtopicsCollect := make([]common.Hash, len(subtopicsList)) - for idx, subtopic := range subtopicsList { - tstr, ok := subtopic.(string) - if !ok { - err := errors.Errorf("invalid subtopic: %s", subtopic) - api.logger.Error("invalid subtopic", "type", fmt.Sprintf("%T", subtopic)) - return nil, err - } - - subtopicsCollect[idx] = common.HexToHash(tstr) - } - - crit.Topics[topicIdx] = subtopicsCollect - } - } - } - - sub, unsubFn, err := api.events.SubscribeLogs(crit) - if err != nil { - api.logger.Error("failed to subscribe logs", "error", err.Error()) - return nil, err - } - - go func() { - ch := sub.Event() - errCh := sub.Err() - for { - select { - case event, ok := <-ch: - if !ok { - return - } - - dataTx, ok := event.Data.(tmtypes.EventDataTx) - if !ok { - api.logger.Debug("event data type mismatch", "type", fmt.Sprintf("%T", event.Data)) - continue - } - - txResponse, err := evmtypes.DecodeTxResponse(dataTx.TxResult.Result.Data) - if err != nil { - api.logger.Error("failed to decode tx response", "error", err.Error()) - return - } - - logs := rpcfilters.FilterLogs(evmtypes.LogsToEthereum(txResponse.Logs), crit.FromBlock, crit.ToBlock, crit.Addresses, crit.Topics) - if len(logs) == 0 { - continue - } - - for _, ethLog := range logs { - res := &SubscriptionNotification{ - Jsonrpc: "2.0", - Method: "eth_subscription", - Params: &SubscriptionResult{ - Subscription: subID, - Result: ethLog, - }, - } - - err = wsConn.WriteJSON(res) - if err != nil { - try(func() { - if err != websocket.ErrCloseSent { - _ = wsConn.Close() - } - }, api.logger, "closing websocket peer sub") - } - } - case err, ok := <-errCh: - if !ok { - return - } - api.logger.Debug("dropping Logs WebSocket subscription", "subscription-id", subID, "error", err.Error()) - } - } - }() - - return unsubFn, nil -} - -func (api *pubSubAPI) subscribePendingTransactions(wsConn *wsConn, subID rpc.ID) (pubsub.UnsubscribeFunc, error) { - sub, unsubFn, err := api.events.SubscribePendingTxs() - if err != nil { - return nil, errors.Wrap(err, "error creating block filter: %s") - } - - go func() { - txsCh := sub.Event() - errCh := sub.Err() - for { - select { - case ev := <-txsCh: - data, ok := ev.Data.(tmtypes.EventDataTx) - if !ok { - api.logger.Debug("event data type mismatch", "type", fmt.Sprintf("%T", ev.Data)) - continue - } - - ethTxs, err := types.RawTxToEthTx(api.clientCtx, data.Tx) - if err != nil { - // not ethereum tx - continue - } - - for _, ethTx := range ethTxs { - // write to ws conn - res := &SubscriptionNotification{ - Jsonrpc: "2.0", - Method: "eth_subscription", - Params: &SubscriptionResult{ - Subscription: subID, - Result: ethTx.Hash, - }, - } - - err = wsConn.WriteJSON(res) - if err != nil { - api.logger.Debug("error writing header, will drop peer", "error", err.Error()) - - try(func() { - if err != websocket.ErrCloseSent { - _ = wsConn.Close() - } - }, api.logger, "closing websocket peer sub") - } - } - case err, ok := <-errCh: - if !ok { - return - } - api.logger.Debug("dropping PendingTransactions WebSocket subscription", subID, "error", err.Error()) - } - } - }() - - return unsubFn, nil -} - -func (api *pubSubAPI) subscribeSyncing(wsConn *wsConn, subID rpc.ID) (pubsub.UnsubscribeFunc, error) { - return nil, errors.New("syncing subscription is not implemented") -} diff --git a/server/json_rpc.go b/server/json_rpc.go index 6c420300..2a67bad8 100644 --- a/server/json_rpc.go +++ b/server/json_rpc.go @@ -1,26 +1,20 @@ package server import ( - "net/http" - "time" - - "github.com/gorilla/mux" - "github.com/rs/cors" + "github.com/tendermint/tendermint/node" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/server" - "github.com/cosmos/cosmos-sdk/server/types" ethlog "github.com/ethereum/go-ethereum/log" - ethrpc "github.com/ethereum/go-ethereum/rpc" + storetypes "github.com/cosmos/cosmos-sdk/store/types" "github.com/stratosnet/stratos-chain/rpc" "github.com/stratosnet/stratos-chain/server/config" + evmkeeper "github.com/stratosnet/stratos-chain/x/evm/keeper" ) // StartJSONRPC starts the JSON-RPC server -func StartJSONRPC(ctx *server.Context, clientCtx client.Context, tmRPCAddr, tmEndpoint string, config config.Config) (*http.Server, chan struct{}, error) { - tmWsClient := ConnectTmWS(tmRPCAddr, tmEndpoint, ctx.Logger) - +func StartJSONRPC(ctx *server.Context, tmNode *node.Node, evmKeeper *evmkeeper.Keeper, ms storetypes.MultiStore, clientCtx client.Context, config config.Config) error { logger := ctx.Logger.With("module", "geth") ethlog.Root().SetHandler(ethlog.FuncHandler(func(r *ethlog.Record) error { switch r.Lvl { @@ -34,65 +28,15 @@ func StartJSONRPC(ctx *server.Context, clientCtx client.Context, tmRPCAddr, tmEn return nil })) - rpcServer := ethrpc.NewServer() - - rpcAPIArr := config.JSONRPC.API - apis := rpc.GetRPCAPIs(ctx, clientCtx, tmWsClient, rpcAPIArr) - - for _, api := range apis { - if err := rpcServer.RegisterName(api.Namespace, api.Service); err != nil { - ctx.Logger.Error( - "failed to register service in JSON RPC namespace", - "namespace", api.Namespace, - "service", api.Service, - ) - return nil, nil, err - } - } - - r := mux.NewRouter() - r.HandleFunc("/", rpcServer.ServeHTTP).Methods("POST") - - handlerWithCors := cors.Default() - if config.API.EnableUnsafeCORS { - handlerWithCors = cors.AllowAll() + apis := rpc.GetRPCAPIs(ctx, tmNode, evmKeeper, ms, clientCtx, config.JSONRPC.API) + web3Srv := rpc.NewWeb3Server(config, logger) + err := web3Srv.StartHTTP(apis) + if err != nil { + return err } - - httpSrv := &http.Server{ - Addr: config.JSONRPC.Address, - Handler: handlerWithCors.Handler(r), - ReadTimeout: config.JSONRPC.HTTPTimeout, - WriteTimeout: config.JSONRPC.HTTPTimeout, - IdleTimeout: config.JSONRPC.HTTPIdleTimeout, - } - httpSrvDone := make(chan struct{}, 1) - - errCh := make(chan error) - go func() { - ctx.Logger.Info("Starting JSON-RPC server", "address", config.JSONRPC.Address) - if err := httpSrv.ListenAndServe(); err != nil { - if err == http.ErrServerClosed { - close(httpSrvDone) - return - } - - ctx.Logger.Error("failed to start JSON-RPC server", "error", err.Error()) - errCh <- err - } - }() - - select { - case err := <-errCh: - ctx.Logger.Error("failed to boot JSON-RPC server", "error", err.Error()) - return nil, nil, err - case <-time.After(types.ServerStartTime): // assume JSON RPC server started successfully + err = web3Srv.StartWS(apis) + if err != nil { + return err } - - ctx.Logger.Info("Starting JSON WebSocket server", "address", config.JSONRPC.WsAddress) - - // allocate separate WS connection to Tendermint - tmWsClient = ConnectTmWS(tmRPCAddr, tmEndpoint, ctx.Logger) - wsSrv := rpc.NewWebsocketsServer(clientCtx, ctx.Logger, tmWsClient, config) - wsSrv.Start() - return httpSrv, httpSrvDone, nil + return nil } diff --git a/server/start.go b/server/start.go index a0d33efc..582a7fbb 100644 --- a/server/start.go +++ b/server/start.go @@ -1,8 +1,6 @@ package server import ( - "context" - "encoding/json" "fmt" "io" "net/http" @@ -38,6 +36,7 @@ import ( "github.com/cosmos/cosmos-sdk/server/types" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" + stosapp "github.com/stratosnet/stratos-chain/app" ethdebug "github.com/stratosnet/stratos-chain/rpc/namespaces/ethereum/debug" "github.com/stratosnet/stratos-chain/server/config" @@ -413,28 +412,10 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty } } - var ( - httpSrv *http.Server - httpSrvDone chan struct{} - ) - if config.JSONRPC.Enable { - genDoc, err := genDocProvider() - if err != nil { - return err - } - var genAppState map[string]interface{} - json.Unmarshal([]byte(genDoc.AppState), &genAppState) - genEvm := genAppState["evm"].(map[string]interface{}) - genEvmParams := genEvm["params"].(map[string]interface{}) - genEvmParamsChainCfg := genEvmParams["chain_config"].(map[string]interface{}) - genEvmParamsChainId := genEvmParamsChainCfg["chain_id"].(string) - - clientCtx := clientCtx.WithChainID(genEvmParamsChainId) - - tmEndpoint := "/websocket" - tmRPCAddr := cfg.RPC.ListenAddress - httpSrv, httpSrvDone, err = StartJSONRPC(ctx, clientCtx, tmRPCAddr, tmEndpoint, config) + evmApp := app.(stosapp.EVMLKeeperApp) + + err = StartJSONRPC(ctx, tmNode, evmApp.GetEVMKeeper(), app.CommitMultiStore(), clientCtx, config) if err != nil { return err } @@ -462,21 +443,6 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty } } - if httpSrv != nil { - shutdownCtx, cancelFn := context.WithTimeout(context.Background(), 10*time.Second) - defer cancelFn() - - if err := httpSrv.Shutdown(shutdownCtx); err != nil { - logger.Error("HTTP server shutdown produced a warning", "error", err.Error()) - } else { - logger.Info("HTTP server shut down, waiting 5 sec") - select { - case <-time.Tick(5 * time.Second): - case <-httpSrvDone: - } - } - } - logger.Info("Bye!") }() diff --git a/x/evm/client/rest/rest.go b/x/evm/client/rest/rest.go index c6927aa5..b4953b55 100644 --- a/x/evm/client/rest/rest.go +++ b/x/evm/client/rest/rest.go @@ -5,7 +5,6 @@ import ( "encoding/hex" "encoding/json" "errors" - "math/big" "net/http" "strings" @@ -19,7 +18,6 @@ import ( "github.com/ethereum/go-ethereum/common" rpctypes "github.com/stratosnet/stratos-chain/rpc/types" - "github.com/stratosnet/stratos-chain/x/evm/types" ) // RegisterTxRoutes - Central function to define routes that get registered by the main application @@ -82,17 +80,6 @@ func getEthTransactionByHash(clientCtx client.Context, hashHex string) ([]byte, return nil, err } - client := types.NewQueryClient(clientCtx) - res, err := client.BaseFee(context.Background(), &types.QueryBaseFeeRequest{}) - if err != nil { - return nil, err - } - - var baseFee *big.Int - if res.BaseFee != nil { - baseFee = res.BaseFee.BigInt() - } - blockHash := common.BytesToHash(block.Block.Header.Hash()) ethTxs, err := rpctypes.RawTxToEthTx(clientCtx, tx.Tx) @@ -101,10 +88,11 @@ func getEthTransactionByHash(clientCtx client.Context, hashHex string) ([]byte, } height := uint64(tx.Height) + txIndex := uint64(tx.Index) for _, ethTx := range ethTxs { if common.HexToHash(ethTx.Hash) == common.BytesToHash(hash) { - rpcTx, err := rpctypes.NewRPCTransaction(ethTx.AsTransaction(), blockHash, height, uint64(tx.Index), baseFee) + rpcTx, err := rpctypes.NewRPCTransaction(ethTx.AsTransaction(), &blockHash, &height, &txIndex) if err != nil { return nil, err } diff --git a/x/evm/keeper/state_transition.go b/x/evm/keeper/state_transition.go index 9103d21a..92c097b8 100644 --- a/x/evm/keeper/state_transition.go +++ b/x/evm/keeper/state_transition.go @@ -3,6 +3,7 @@ package keeper import ( "math" "math/big" + "sync" tmtypes "github.com/tendermint/tendermint/types" @@ -107,6 +108,7 @@ func (k Keeper) VMConfig(ctx sdk.Context, msg core.Message, cfg *types.EVMConfig var debug bool if _, ok := tracer.(types.NoOpTracer); !ok { debug = true + noBaseFee = true } return vm.Config{ @@ -122,6 +124,9 @@ func (k Keeper) VMConfig(ctx sdk.Context, msg core.Message, cfg *types.EVMConfig // 2. The requested height is from an previous height from the same chain epoch // 3. The requested height is from a height greater than the latest one func (k Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc { + cache := make(map[int64]common.Hash) + var rw sync.Mutex + return func(height uint64) common.Hash { h, err := stratos.SafeInt64(height) if err != nil { @@ -135,24 +140,20 @@ func (k Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc { // hash directly from the context. // Note: The headerHash is only set at begin block, it will be nil in case of a query context headerHash := ctx.HeaderHash() - if len(headerHash) != 0 { - return common.BytesToHash(headerHash) - } - - // only recompute the hash if not set (eg: checkTxState) - contextBlockHeader := ctx.BlockHeader() - header, err := tmtypes.HeaderFromProto(&contextBlockHeader) - if err != nil { - k.Logger(ctx).Error("failed to cast tendermint header from proto", "error", err) - return common.Hash{} - } - - headerHash = header.Hash() return common.BytesToHash(headerHash) case ctx.BlockHeight() > h: // Case 2: if the chain is not the current height we need to retrieve the hash from the store for the // current chain epoch. This only applies if the current height is greater than the requested height. + + // NOTE: In case of concurrency + rw.Lock() + defer rw.Unlock() + + if hash, ok := cache[h]; ok { + return hash + } + histInfo, found := k.stakingKeeper.GetHistoricalInfo(ctx, h) if !found { k.Logger(ctx).Debug("historical info not found", "height", h) @@ -165,7 +166,9 @@ func (k Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc { return common.Hash{} } - return common.BytesToHash(header.Hash()) + hash := common.BytesToHash(header.Hash()) + cache[h] = hash + return hash default: // Case 3: heights greater than the current one returns an empty hash. return common.Hash{} @@ -374,14 +377,29 @@ func (k *Keeper) ApplyMessageWithConfig(ctx sdk.Context, msg core.Message, trace stateDB.PrepareAccessList(msg.From(), msg.To(), vm.ActivePrecompiles(rules), msg.AccessList()) } + // NOTE: In order to achive this, nonce should be checked in ante handler and increased, othervise + // it could make pottential nonce overide with double spend or contract rewrite + // take over the nonce management from evm: + // reset sender's nonce to msg.Nonce() before calling evm on msg nonce + // as nonce already increased in db + // TODO: UNCOMMENT THIS FOR PROD!!!!!! + // stateDB.SetNonce(sender.Address(), msg.Nonce()) + if contractCreation { - // take over the nonce management from evm: - // - reset sender's nonce to msg.Nonce() before calling evm. - // - increase sender's nonce by one no matter the result. + // no need to increase nonce here as contract as during contract creation: + // - tx.origin nonce increase automatically + // - if IsEIP158 enabled, contract nonce will be set as 1 + + // NOTE: REMOVE THIS FOR PROD!!!!!!!!!!! stateDB.SetNonce(sender.Address(), msg.Nonce()) ret, _, leftoverGas, vmErr = evm.Create(sender, msg.Data(), leftoverGas, msg.Value()) + + // NOTE: REMOVE THIS FOR PROD!!!!!!!!!!! stateDB.SetNonce(sender.Address(), msg.Nonce()+1) } else { + // should be incresed before call on nonce from msg so we make sure nonce remaining same as on init tx + // TODO: UNCOMMENT THIS FOR PROD!!!!!! + // stateDB.SetNonce(sender.Address(), msg.Nonce()+1) ret, leftoverGas, vmErr = evm.Call(sender, *msg.To(), msg.Data(), leftoverGas, msg.Value()) } diff --git a/x/evm/tracers/js/bigint.go b/x/evm/tracers/js/bigint.go new file mode 100644 index 00000000..9aeb3304 --- /dev/null +++ b/x/evm/tracers/js/bigint.go @@ -0,0 +1,20 @@ +// Copyright 2021 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package js + +// bigIntegerJS is the minified version of https://github.com/peterolson/BigInteger.js. +const bigIntegerJS = `var bigInt=function(undefined){"use strict";var BASE=1e7,LOG_BASE=7,MAX_INT=9007199254740992,MAX_INT_ARR=smallToArray(MAX_INT),LOG_MAX_INT=Math.log(MAX_INT);function Integer(v,radix){if(typeof v==="undefined")return Integer[0];if(typeof radix!=="undefined")return+radix===10?parseValue(v):parseBase(v,radix);return parseValue(v)}function BigInteger(value,sign){this.value=value;this.sign=sign;this.isSmall=false}BigInteger.prototype=Object.create(Integer.prototype);function SmallInteger(value){this.value=value;this.sign=value<0;this.isSmall=true}SmallInteger.prototype=Object.create(Integer.prototype);function isPrecise(n){return-MAX_INT0)return Math.floor(n);return Math.ceil(n)}function add(a,b){var l_a=a.length,l_b=b.length,r=new Array(l_a),carry=0,base=BASE,sum,i;for(i=0;i=base?1:0;r[i]=sum-carry*base}while(i0)r.push(carry);return r}function addAny(a,b){if(a.length>=b.length)return add(a,b);return add(b,a)}function addSmall(a,carry){var l=a.length,r=new Array(l),base=BASE,sum,i;for(i=0;i0){r[i++]=carry%base;carry=Math.floor(carry/base)}return r}BigInteger.prototype.add=function(v){var n=parseValue(v);if(this.sign!==n.sign){return this.subtract(n.negate())}var a=this.value,b=n.value;if(n.isSmall){return new BigInteger(addSmall(a,Math.abs(b)),this.sign)}return new BigInteger(addAny(a,b),this.sign)};BigInteger.prototype.plus=BigInteger.prototype.add;SmallInteger.prototype.add=function(v){var n=parseValue(v);var a=this.value;if(a<0!==n.sign){return this.subtract(n.negate())}var b=n.value;if(n.isSmall){if(isPrecise(a+b))return new SmallInteger(a+b);b=smallToArray(Math.abs(b))}return new BigInteger(addSmall(b,Math.abs(a)),a<0)};SmallInteger.prototype.plus=SmallInteger.prototype.add;function subtract(a,b){var a_l=a.length,b_l=b.length,r=new Array(a_l),borrow=0,base=BASE,i,difference;for(i=0;i=0){value=subtract(a,b)}else{value=subtract(b,a);sign=!sign}value=arrayToSmall(value);if(typeof value==="number"){if(sign)value=-value;return new SmallInteger(value)}return new BigInteger(value,sign)}function subtractSmall(a,b,sign){var l=a.length,r=new Array(l),carry=-b,base=BASE,i,difference;for(i=0;i=0)};SmallInteger.prototype.minus=SmallInteger.prototype.subtract;BigInteger.prototype.negate=function(){return new BigInteger(this.value,!this.sign)};SmallInteger.prototype.negate=function(){var sign=this.sign;var small=new SmallInteger(-this.value);small.sign=!sign;return small};BigInteger.prototype.abs=function(){return new BigInteger(this.value,false)};SmallInteger.prototype.abs=function(){return new SmallInteger(Math.abs(this.value))};function multiplyLong(a,b){var a_l=a.length,b_l=b.length,l=a_l+b_l,r=createArray(l),base=BASE,product,carry,i,a_i,b_j;for(i=0;i0){r[i++]=carry%base;carry=Math.floor(carry/base)}return r}function shiftLeft(x,n){var r=[];while(n-- >0)r.push(0);return r.concat(x)}function multiplyKaratsuba(x,y){var n=Math.max(x.length,y.length);if(n<=30)return multiplyLong(x,y);n=Math.ceil(n/2);var b=x.slice(n),a=x.slice(0,n),d=y.slice(n),c=y.slice(0,n);var ac=multiplyKaratsuba(a,c),bd=multiplyKaratsuba(b,d),abcd=multiplyKaratsuba(addAny(a,b),addAny(c,d));var product=addAny(addAny(ac,shiftLeft(subtract(subtract(abcd,ac),bd),n)),shiftLeft(bd,2*n));trim(product);return product}function useKaratsuba(l1,l2){return-.012*l1-.012*l2+15e-6*l1*l2>0}BigInteger.prototype.multiply=function(v){var n=parseValue(v),a=this.value,b=n.value,sign=this.sign!==n.sign,abs;if(n.isSmall){if(b===0)return Integer[0];if(b===1)return this;if(b===-1)return this.negate();abs=Math.abs(b);if(abs=0;shift--){quotientDigit=base-1;if(remainder[shift+b_l]!==divisorMostSignificantDigit){quotientDigit=Math.floor((remainder[shift+b_l]*base+remainder[shift+b_l-1])/divisorMostSignificantDigit)}carry=0;borrow=0;l=divisor.length;for(i=0;ib_l){highx=(highx+1)*base}guess=Math.ceil(highx/highy);do{check=multiplySmall(b,guess);if(compareAbs(check,part)<=0)break;guess--}while(guess);result.push(guess);part=subtract(part,check)}result.reverse();return[arrayToSmall(result),arrayToSmall(part)]}function divModSmall(value,lambda){var length=value.length,quotient=createArray(length),base=BASE,i,q,remainder,divisor;remainder=0;for(i=length-1;i>=0;--i){divisor=remainder*base+value[i];q=truncate(divisor/lambda);remainder=divisor-q*lambda;quotient[i]=q|0}return[quotient,remainder|0]}function divModAny(self,v){var value,n=parseValue(v);var a=self.value,b=n.value;var quotient;if(b===0)throw new Error("Cannot divide by zero");if(self.isSmall){if(n.isSmall){return[new SmallInteger(truncate(a/b)),new SmallInteger(a%b)]}return[Integer[0],self]}if(n.isSmall){if(b===1)return[self,Integer[0]];if(b==-1)return[self.negate(),Integer[0]];var abs=Math.abs(b);if(absb.length?1:-1}for(var i=a.length-1;i>=0;i--){if(a[i]!==b[i])return a[i]>b[i]?1:-1}return 0}BigInteger.prototype.compareAbs=function(v){var n=parseValue(v),a=this.value,b=n.value;if(n.isSmall)return 1;return compareAbs(a,b)};SmallInteger.prototype.compareAbs=function(v){var n=parseValue(v),a=Math.abs(this.value),b=n.value;if(n.isSmall){b=Math.abs(b);return a===b?0:a>b?1:-1}return-1};BigInteger.prototype.compare=function(v){if(v===Infinity){return-1}if(v===-Infinity){return 1}var n=parseValue(v),a=this.value,b=n.value;if(this.sign!==n.sign){return n.sign?1:-1}if(n.isSmall){return this.sign?-1:1}return compareAbs(a,b)*(this.sign?-1:1)};BigInteger.prototype.compareTo=BigInteger.prototype.compare;SmallInteger.prototype.compare=function(v){if(v===Infinity){return-1}if(v===-Infinity){return 1}var n=parseValue(v),a=this.value,b=n.value;if(n.isSmall){return a==b?0:a>b?1:-1}if(a<0!==n.sign){return a<0?-1:1}return a<0?1:-1};SmallInteger.prototype.compareTo=SmallInteger.prototype.compare;BigInteger.prototype.equals=function(v){return this.compare(v)===0};SmallInteger.prototype.eq=SmallInteger.prototype.equals=BigInteger.prototype.eq=BigInteger.prototype.equals;BigInteger.prototype.notEquals=function(v){return this.compare(v)!==0};SmallInteger.prototype.neq=SmallInteger.prototype.notEquals=BigInteger.prototype.neq=BigInteger.prototype.notEquals;BigInteger.prototype.greater=function(v){return this.compare(v)>0};SmallInteger.prototype.gt=SmallInteger.prototype.greater=BigInteger.prototype.gt=BigInteger.prototype.greater;BigInteger.prototype.lesser=function(v){return this.compare(v)<0};SmallInteger.prototype.lt=SmallInteger.prototype.lesser=BigInteger.prototype.lt=BigInteger.prototype.lesser;BigInteger.prototype.greaterOrEquals=function(v){return this.compare(v)>=0};SmallInteger.prototype.geq=SmallInteger.prototype.greaterOrEquals=BigInteger.prototype.geq=BigInteger.prototype.greaterOrEquals;BigInteger.prototype.lesserOrEquals=function(v){return this.compare(v)<=0};SmallInteger.prototype.leq=SmallInteger.prototype.lesserOrEquals=BigInteger.prototype.leq=BigInteger.prototype.lesserOrEquals;BigInteger.prototype.isEven=function(){return(this.value[0]&1)===0};SmallInteger.prototype.isEven=function(){return(this.value&1)===0};BigInteger.prototype.isOdd=function(){return(this.value[0]&1)===1};SmallInteger.prototype.isOdd=function(){return(this.value&1)===1};BigInteger.prototype.isPositive=function(){return!this.sign};SmallInteger.prototype.isPositive=function(){return this.value>0};BigInteger.prototype.isNegative=function(){return this.sign};SmallInteger.prototype.isNegative=function(){return this.value<0};BigInteger.prototype.isUnit=function(){return false};SmallInteger.prototype.isUnit=function(){return Math.abs(this.value)===1};BigInteger.prototype.isZero=function(){return false};SmallInteger.prototype.isZero=function(){return this.value===0};BigInteger.prototype.isDivisibleBy=function(v){var n=parseValue(v);var value=n.value;if(value===0)return false;if(value===1)return true;if(value===2)return this.isEven();return this.mod(n).equals(Integer[0])};SmallInteger.prototype.isDivisibleBy=BigInteger.prototype.isDivisibleBy;function isBasicPrime(v){var n=v.abs();if(n.isUnit())return false;if(n.equals(2)||n.equals(3)||n.equals(5))return true;if(n.isEven()||n.isDivisibleBy(3)||n.isDivisibleBy(5))return false;if(n.lesser(25))return true}BigInteger.prototype.isPrime=function(){var isPrime=isBasicPrime(this);if(isPrime!==undefined)return isPrime;var n=this.abs(),nPrev=n.prev();var a=[2,3,5,7,11,13,17,19],b=nPrev,d,t,i,x;while(b.isEven())b=b.divide(2);for(i=0;i-MAX_INT)return new SmallInteger(value-1);return new BigInteger(MAX_INT_ARR,true)};var powersOfTwo=[1];while(2*powersOfTwo[powersOfTwo.length-1]<=BASE)powersOfTwo.push(2*powersOfTwo[powersOfTwo.length-1]);var powers2Length=powersOfTwo.length,highestPower2=powersOfTwo[powers2Length-1];function shift_isSmall(n){return(typeof n==="number"||typeof n==="string")&&+Math.abs(n)<=BASE||n instanceof BigInteger&&n.value.length<=1}BigInteger.prototype.shiftLeft=function(n){if(!shift_isSmall(n)){throw new Error(String(n)+" is too large for shifting.")}n=+n;if(n<0)return this.shiftRight(-n);var result=this;while(n>=powers2Length){result=result.multiply(highestPower2);n-=powers2Length-1}return result.multiply(powersOfTwo[n])};SmallInteger.prototype.shiftLeft=BigInteger.prototype.shiftLeft;BigInteger.prototype.shiftRight=function(n){var remQuo;if(!shift_isSmall(n)){throw new Error(String(n)+" is too large for shifting.")}n=+n;if(n<0)return this.shiftLeft(-n);var result=this;while(n>=powers2Length){if(result.isZero())return result;remQuo=divModAny(result,highestPower2);result=remQuo[1].isNegative()?remQuo[0].prev():remQuo[0];n-=powers2Length-1}remQuo=divModAny(result,powersOfTwo[n]);return remQuo[1].isNegative()?remQuo[0].prev():remQuo[0]};SmallInteger.prototype.shiftRight=BigInteger.prototype.shiftRight;function bitwise(x,y,fn){y=parseValue(y);var xSign=x.isNegative(),ySign=y.isNegative();var xRem=xSign?x.not():x,yRem=ySign?y.not():y;var xDigit=0,yDigit=0;var xDivMod=null,yDivMod=null;var result=[];while(!xRem.isZero()||!yRem.isZero()){xDivMod=divModAny(xRem,highestPower2);xDigit=xDivMod[1].toJSNumber();if(xSign){xDigit=highestPower2-1-xDigit}yDivMod=divModAny(yRem,highestPower2);yDigit=yDivMod[1].toJSNumber();if(ySign){yDigit=highestPower2-1-yDigit}xRem=xDivMod[0];yRem=yDivMod[0];result.push(fn(xDigit,yDigit))}var sum=fn(xSign?1:0,ySign?1:0)!==0?bigInt(-1):bigInt(0);for(var i=result.length-1;i>=0;i-=1){sum=sum.multiply(highestPower2).add(bigInt(result[i]))}return sum}BigInteger.prototype.not=function(){return this.negate().prev()};SmallInteger.prototype.not=BigInteger.prototype.not;BigInteger.prototype.and=function(n){return bitwise(this,n,function(a,b){return a&b})};SmallInteger.prototype.and=BigInteger.prototype.and;BigInteger.prototype.or=function(n){return bitwise(this,n,function(a,b){return a|b})};SmallInteger.prototype.or=BigInteger.prototype.or;BigInteger.prototype.xor=function(n){return bitwise(this,n,function(a,b){return a^b})};SmallInteger.prototype.xor=BigInteger.prototype.xor;var LOBMASK_I=1<<30,LOBMASK_BI=(BASE&-BASE)*(BASE&-BASE)|LOBMASK_I;function roughLOB(n){var v=n.value,x=typeof v==="number"?v|LOBMASK_I:v[0]+v[1]*BASE|LOBMASK_BI;return x&-x}function max(a,b){a=parseValue(a);b=parseValue(b);return a.greater(b)?a:b}function min(a,b){a=parseValue(a);b=parseValue(b);return a.lesser(b)?a:b}function gcd(a,b){a=parseValue(a).abs();b=parseValue(b).abs();if(a.equals(b))return a;if(a.isZero())return b;if(b.isZero())return a;var c=Integer[1],d,t;while(a.isEven()&&b.isEven()){d=Math.min(roughLOB(a),roughLOB(b));a=a.divide(d);b=b.divide(d);c=c.multiply(d)}while(a.isEven()){a=a.divide(roughLOB(a))}do{while(b.isEven()){b=b.divide(roughLOB(b))}if(a.greater(b)){t=b;b=a;a=t}b=b.subtract(a)}while(!b.isZero());return c.isUnit()?a:a.multiply(c)}function lcm(a,b){a=parseValue(a).abs();b=parseValue(b).abs();return a.divide(gcd(a,b)).multiply(b)}function randBetween(a,b){a=parseValue(a);b=parseValue(b);var low=min(a,b),high=max(a,b);var range=high.subtract(low).add(1);if(range.isSmall)return low.add(Math.floor(Math.random()*range));var length=range.value.length-1;var result=[],restricted=true;for(var i=length;i>=0;i--){var top=restricted?range.value[i]:BASE;var digit=truncate(Math.random()*top);result.unshift(digit);if(digit=absBase){if(c==="1"&&absBase===1)continue;throw new Error(c+" is not a valid digit in base "+base+".")}else if(c.charCodeAt(0)-87>=absBase){throw new Error(c+" is not a valid digit in base "+base+".")}}}if(2<=base&&base<=36){if(length<=LOG_MAX_INT/Math.log(base)){var result=parseInt(text,base);if(isNaN(result)){throw new Error(c+" is not a valid digit in base "+base+".")}return new SmallInteger(parseInt(text,base))}}base=parseValue(base);var digits=[];var isNegative=text[0]==="-";for(i=isNegative?1:0;i");digits.push(parseValue(text.slice(start+1,i)))}else throw new Error(c+" is not a valid character")}return parseBaseFromArray(digits,base,isNegative)};function parseBaseFromArray(digits,base,isNegative){var val=Integer[0],pow=Integer[1],i;for(i=digits.length-1;i>=0;i--){val=val.add(digits[i].times(pow));pow=pow.times(base)}return isNegative?val.negate():val}function stringify(digit){var v=digit.value;if(typeof v==="number")v=[v];if(v.length===1&&v[0]<=35){return"0123456789abcdefghijklmnopqrstuvwxyz".charAt(v[0])}return"<"+v+">"}function toBase(n,base){base=bigInt(base);if(base.isZero()){if(n.isZero())return"0";throw new Error("Cannot convert nonzero numbers to base 0.")}if(base.equals(-1)){if(n.isZero())return"0";if(n.isNegative())return new Array(1-n).join("10");return"1"+new Array(+n).join("01")}var minusSign="";if(n.isNegative()&&base.isPositive()){minusSign="-";n=n.abs()}if(base.equals(1)){if(n.isZero())return"0";return minusSign+new Array(+n+1).join(1)}var out=[];var left=n,divmod;while(left.isNegative()||left.compareAbs(base)>=0){divmod=left.divmod(base);left=divmod.quotient;var digit=divmod.remainder;if(digit.isNegative()){digit=base.minus(digit).abs();left=left.next()}out.push(stringify(digit))}out.push(stringify(left));return minusSign+out.reverse().join("")}BigInteger.prototype.toString=function(radix){if(radix===undefined)radix=10;if(radix!==10)return toBase(this,radix);var v=this.value,l=v.length,str=String(v[--l]),zeros="0000000",digit;while(--l>=0){digit=String(v[l]);str+=zeros.slice(digit.length)+digit}var sign=this.sign?"-":"";return sign+str};SmallInteger.prototype.toString=function(radix){if(radix===undefined)radix=10;if(radix!=10)return toBase(this,radix);return String(this.value)};BigInteger.prototype.toJSON=SmallInteger.prototype.toJSON=function(){return this.toString()};BigInteger.prototype.valueOf=function(){return+this.toString()};BigInteger.prototype.toJSNumber=BigInteger.prototype.valueOf;SmallInteger.prototype.valueOf=function(){return this.value};SmallInteger.prototype.toJSNumber=SmallInteger.prototype.valueOf;function parseStringValue(v){if(isPrecise(+v)){var x=+v;if(x===truncate(x))return new SmallInteger(x);throw"Invalid integer: "+v}var sign=v[0]==="-";if(sign)v=v.slice(1);var split=v.split(/e/i);if(split.length>2)throw new Error("Invalid integer: "+split.join("e"));if(split.length===2){var exp=split[1];if(exp[0]==="+")exp=exp.slice(1);exp=+exp;if(exp!==truncate(exp)||!isPrecise(exp))throw new Error("Invalid integer: "+exp+" is not a valid exponent.");var text=split[0];var decimalPlace=text.indexOf(".");if(decimalPlace>=0){exp-=text.length-decimalPlace-1;text=text.slice(0,decimalPlace)+text.slice(decimalPlace+1)}if(exp<0)throw new Error("Cannot include negative exponent part for integers");text+=new Array(exp+1).join("0");v=text}var isValid=/^([0-9][0-9]*)$/.test(v);if(!isValid)throw new Error("Invalid integer: "+v);var r=[],max=v.length,l=LOG_BASE,min=max-l;while(max>0){r.push(+v.slice(min,max));min-=l;if(min<0)min=0;max-=l}trim(r);return new BigInteger(r,sign)}function parseNumberValue(v){if(isPrecise(v)){if(v!==truncate(v))throw new Error(v+" is not an integer.");return new SmallInteger(v)}return parseStringValue(v.toString())}function parseValue(v){if(typeof v==="number"){return parseNumberValue(v)}if(typeof v==="string"){return parseStringValue(v)}return v}for(var i=0;i<1e3;i++){Integer[i]=new SmallInteger(i);if(i>0)Integer[-i]=new SmallInteger(-i)}Integer.one=Integer[1];Integer.zero=Integer[0];Integer.minusOne=Integer[-1];Integer.max=max;Integer.min=min;Integer.gcd=gcd;Integer.lcm=lcm;Integer.isInstance=function(x){return x instanceof BigInteger||x instanceof SmallInteger};Integer.randBetween=randBetween;Integer.fromArray=function(digits,base,isNegative){return parseBaseFromArray(digits.map(parseValue),parseValue(base||10),isNegative)};return Integer}();if(typeof module!=="undefined"&&module.hasOwnProperty("exports")){module.exports=bigInt}if(typeof define==="function"&&define.amd){define("big-integer",[],function(){return bigInt})}; bigInt` diff --git a/x/evm/tracers/js/goja.go b/x/evm/tracers/js/goja.go new file mode 100644 index 00000000..adbcfcaf --- /dev/null +++ b/x/evm/tracers/js/goja.go @@ -0,0 +1,960 @@ +// Copyright 2022 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package js + +import ( + "encoding/json" + "errors" + "fmt" + "math/big" + "time" + + "github.com/dop251/goja" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth/tracers" + jsassets "github.com/stratosnet/stratos-chain/x/evm/tracers/js/internal/tracers" +) + +var assetTracers = make(map[string]string) + +// InitTracer retrieves the JavaScript transaction tracers included in go-ethereum. +func InitTracer() { + var err error + assetTracers, err = jsassets.Load() + if err != nil { + panic(err) + } + tracers.RegisterLookup(true, newJsTracer) +} + +// bigIntProgram is compiled once and the exported function mostly invoked to convert +// hex strings into big ints. +var bigIntProgram = goja.MustCompile("bigInt", bigIntegerJS, false) + +type toBigFn = func(vm *goja.Runtime, val string) (goja.Value, error) +type toBufFn = func(vm *goja.Runtime, val []byte) (goja.Value, error) +type fromBufFn = func(vm *goja.Runtime, buf goja.Value, allowString bool) ([]byte, error) + +func toBuf(vm *goja.Runtime, bufType goja.Value, val []byte) (goja.Value, error) { + // bufType is usually Uint8Array. This is equivalent to `new Uint8Array(val)` in JS. + return vm.New(bufType, vm.ToValue(vm.NewArrayBuffer(val))) +} + +func fromBuf(vm *goja.Runtime, bufType goja.Value, buf goja.Value, allowString bool) ([]byte, error) { + obj := buf.ToObject(vm) + switch obj.ClassName() { + case "String": + if !allowString { + break + } + return common.FromHex(obj.String()), nil + + case "Array": + var b []byte + if err := vm.ExportTo(buf, &b); err != nil { + return nil, err + } + return b, nil + + case "Object": + if !obj.Get("constructor").SameAs(bufType) { + break + } + b := obj.Get("buffer").Export().(goja.ArrayBuffer).Bytes() + return b, nil + } + return nil, fmt.Errorf("invalid buffer type") +} + +// jsTracer is an implementation of the Tracer interface which evaluates +// JS functions on the relevant EVM hooks. It uses Goja as its JS engine. +type jsTracer struct { + vm *goja.Runtime + env *vm.EVM + toBig toBigFn // Converts a hex string into a JS bigint + toBuf toBufFn // Converts a []byte into a JS buffer + fromBuf fromBufFn // Converts an array, hex string or Uint8Array to a []byte + ctx map[string]goja.Value // KV-bag passed to JS in `result` + activePrecompiles []common.Address // List of active precompiles at current block + traceStep bool // True if tracer object exposes a `step()` method + traceFrame bool // True if tracer object exposes the `enter()` and `exit()` methods + gasLimit uint64 // Amount of gas bought for the whole tx + err error // Any error that should stop tracing + obj *goja.Object // Trace object + + // Methods exposed by tracer + result goja.Callable + fault goja.Callable + step goja.Callable + enter goja.Callable + exit goja.Callable + + // Underlying structs being passed into JS + log *steplog + frame *callframe + frameResult *callframeResult + + // Goja-wrapping of types prepared for JS consumption + logValue goja.Value + dbValue goja.Value + frameValue goja.Value + frameResultValue goja.Value +} + +// newJsTracer instantiates a new JS tracer instance. code is either +// the name of a built-in JS tracer or a Javascript snippet which +// evaluates to an expression returning an object with certain methods. +// The methods `result` and `fault` are required to be present. +// The methods `step`, `enter`, and `exit` are optional, but note that +// `enter` and `exit` always go together. +func newJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) { + if c, ok := assetTracers[code]; ok { + code = c + } + vm := goja.New() + // By default field names are exported to JS as is, i.e. capitalized. + vm.SetFieldNameMapper(goja.UncapFieldNameMapper()) + t := &jsTracer{ + vm: vm, + ctx: make(map[string]goja.Value), + } + if ctx == nil { + ctx = new(tracers.Context) + } + if ctx.BlockHash != (common.Hash{}) { + t.ctx["blockHash"] = vm.ToValue(ctx.BlockHash.Bytes()) + if ctx.TxHash != (common.Hash{}) { + t.ctx["txIndex"] = vm.ToValue(ctx.TxIndex) + t.ctx["txHash"] = vm.ToValue(ctx.TxHash.Bytes()) + } + } + + t.setTypeConverters() + t.setBuiltinFunctions() + ret, err := vm.RunString("(" + code + ")") + if err != nil { + return nil, err + } + // Check tracer's interface for required and optional methods. + obj := ret.ToObject(vm) + result, ok := goja.AssertFunction(obj.Get("result")) + if !ok { + return nil, errors.New("trace object must expose a function result()") + } + fault, ok := goja.AssertFunction(obj.Get("fault")) + if !ok { + return nil, errors.New("trace object must expose a function fault()") + } + step, ok := goja.AssertFunction(obj.Get("step")) + t.traceStep = ok + enter, hasEnter := goja.AssertFunction(obj.Get("enter")) + exit, hasExit := goja.AssertFunction(obj.Get("exit")) + if hasEnter != hasExit { + return nil, errors.New("trace object must expose either both or none of enter() and exit()") + } + t.traceFrame = hasEnter + t.obj = obj + t.step = step + t.enter = enter + t.exit = exit + t.result = result + t.fault = fault + + // Pass in config + if setup, ok := goja.AssertFunction(obj.Get("setup")); ok { + cfgStr := "{}" + if cfg != nil { + cfgStr = string(cfg) + } + if _, err := setup(obj, vm.ToValue(cfgStr)); err != nil { + return nil, err + } + } + // Setup objects carrying data to JS. These are created once and re-used. + t.log = &steplog{ + vm: vm, + op: &opObj{vm: vm}, + memory: &memoryObj{vm: vm, toBig: t.toBig, toBuf: t.toBuf}, + stack: &stackObj{vm: vm, toBig: t.toBig}, + contract: &contractObj{vm: vm, toBig: t.toBig, toBuf: t.toBuf}, + } + t.frame = &callframe{vm: vm, toBig: t.toBig, toBuf: t.toBuf} + t.frameResult = &callframeResult{vm: vm, toBuf: t.toBuf} + t.frameValue = t.frame.setupObject() + t.frameResultValue = t.frameResult.setupObject() + t.logValue = t.log.setupObject() + return t, nil +} + +// CaptureTxStart implements the Tracer interface and is invoked at the beginning of +// transaction processing. +func (t *jsTracer) CaptureTxStart(gasLimit uint64) { + t.gasLimit = gasLimit +} + +// CaptureTxStart implements the Tracer interface and is invoked at the end of +// transaction processing. +func (t *jsTracer) CaptureTxEnd(restGas uint64) {} + +// CaptureStart implements the Tracer interface to initialize the tracing operation. +func (t *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { + t.env = env + db := &dbObj{db: env.StateDB, vm: t.vm, toBig: t.toBig, toBuf: t.toBuf, fromBuf: t.fromBuf} + t.dbValue = db.setupObject() + if create { + t.ctx["type"] = t.vm.ToValue("CREATE") + } else { + t.ctx["type"] = t.vm.ToValue("CALL") + } + t.ctx["from"] = t.vm.ToValue(from.Bytes()) + t.ctx["to"] = t.vm.ToValue(to.Bytes()) + t.ctx["input"] = t.vm.ToValue(input) + t.ctx["gas"] = t.vm.ToValue(gas) + t.ctx["gasPrice"] = t.vm.ToValue(env.TxContext.GasPrice) + valueBig, err := t.toBig(t.vm, value.String()) + if err != nil { + t.err = err + return + } + t.ctx["value"] = valueBig + t.ctx["block"] = t.vm.ToValue(env.Context.BlockNumber.Uint64()) + // Update list of precompiles based on current block + rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil) + t.activePrecompiles = vm.ActivePrecompiles(rules) + t.ctx["intrinsicGas"] = t.vm.ToValue(t.gasLimit - gas) +} + +// CaptureState implements the Tracer interface to trace a single step of VM execution. +func (t *jsTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { + if !t.traceStep { + return + } + if t.err != nil { + return + } + + log := t.log + log.op.op = op + log.memory.memory = scope.Memory + log.stack.stack = scope.Stack + log.contract.contract = scope.Contract + log.pc = uint(pc) + log.gas = uint(gas) + log.cost = uint(cost) + log.depth = uint(depth) + log.err = err + if _, err := t.step(t.obj, t.logValue, t.dbValue); err != nil { + t.onError("step", err) + } +} + +// CaptureFault implements the Tracer interface to trace an execution fault +func (t *jsTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) { + if t.err != nil { + return + } + // Other log fields have been already set as part of the last CaptureState. + t.log.err = err + if _, err := t.fault(t.obj, t.logValue, t.dbValue); err != nil { + t.onError("fault", err) + } +} + +// CaptureEnd is called after the call finishes to finalize the tracing. +func (t *jsTracer) CaptureEnd(output []byte, gasUsed uint64, duration time.Duration, err error) { + t.ctx["output"] = t.vm.ToValue(output) + t.ctx["time"] = t.vm.ToValue(duration.String()) + t.ctx["gasUsed"] = t.vm.ToValue(gasUsed) + if err != nil { + t.ctx["error"] = t.vm.ToValue(err.Error()) + } +} + +// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *jsTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + if !t.traceFrame { + return + } + if t.err != nil { + return + } + + t.frame.typ = typ.String() + t.frame.from = from + t.frame.to = to + t.frame.input = common.CopyBytes(input) + t.frame.gas = uint(gas) + t.frame.value = nil + if value != nil { + t.frame.value = new(big.Int).SetBytes(value.Bytes()) + } + + if _, err := t.enter(t.obj, t.frameValue); err != nil { + t.onError("enter", err) + } +} + +// CaptureExit is called when EVM exits a scope, even if the scope didn't +// execute any code. +func (t *jsTracer) CaptureExit(output []byte, gasUsed uint64, err error) { + if !t.traceFrame { + return + } + + t.frameResult.gasUsed = uint(gasUsed) + t.frameResult.output = common.CopyBytes(output) + t.frameResult.err = err + + if _, err := t.exit(t.obj, t.frameResultValue); err != nil { + t.onError("exit", err) + } +} + +// GetResult calls the Javascript 'result' function and returns its value, or any accumulated error +func (t *jsTracer) GetResult() (json.RawMessage, error) { + ctx := t.vm.ToValue(t.ctx) + res, err := t.result(t.obj, ctx, t.dbValue) + if err != nil { + return nil, wrapError("result", err) + } + encoded, err := json.Marshal(res) + if err != nil { + return nil, err + } + return json.RawMessage(encoded), t.err +} + +// Stop terminates execution of the tracer at the first opportune moment. +func (t *jsTracer) Stop(err error) { + t.vm.Interrupt(err) +} + +// onError is called anytime the running JS code is interrupted +// and returns an error. It in turn pings the EVM to cancel its +// execution. +func (t *jsTracer) onError(context string, err error) { + t.err = wrapError(context, err) + // `env` is set on CaptureStart which comes before any JS execution. + // So it should be non-nil. + t.env.Cancel() +} + +func wrapError(context string, err error) error { + return fmt.Errorf("%v in server-side tracer function '%v'", err, context) +} + +// setBuiltinFunctions injects Go functions which are available to tracers into the environment. +// It depends on type converters having been set up. +func (t *jsTracer) setBuiltinFunctions() { + vm := t.vm + // TODO: load console from goja-nodejs + vm.Set("toHex", func(v goja.Value) string { + b, err := t.fromBuf(vm, v, false) + if err != nil { + vm.Interrupt(err) + return "" + } + return hexutil.Encode(b) + }) + vm.Set("toWord", func(v goja.Value) goja.Value { + // TODO: add test with []byte len < 32 or > 32 + b, err := t.fromBuf(vm, v, true) + if err != nil { + vm.Interrupt(err) + return nil + } + b = common.BytesToHash(b).Bytes() + res, err := t.toBuf(vm, b) + if err != nil { + vm.Interrupt(err) + return nil + } + return res + }) + vm.Set("toAddress", func(v goja.Value) goja.Value { + a, err := t.fromBuf(vm, v, true) + if err != nil { + vm.Interrupt(err) + return nil + } + a = common.BytesToAddress(a).Bytes() + res, err := t.toBuf(vm, a) + if err != nil { + vm.Interrupt(err) + return nil + } + return res + }) + vm.Set("toContract", func(from goja.Value, nonce uint) goja.Value { + a, err := t.fromBuf(vm, from, true) + if err != nil { + vm.Interrupt(err) + return nil + } + addr := common.BytesToAddress(a) + b := crypto.CreateAddress(addr, uint64(nonce)).Bytes() + res, err := t.toBuf(vm, b) + if err != nil { + vm.Interrupt(err) + return nil + } + return res + }) + vm.Set("toContract2", func(from goja.Value, salt string, initcode goja.Value) goja.Value { + a, err := t.fromBuf(vm, from, true) + if err != nil { + vm.Interrupt(err) + return nil + } + addr := common.BytesToAddress(a) + code, err := t.fromBuf(vm, initcode, true) + if err != nil { + vm.Interrupt(err) + return nil + } + code = common.CopyBytes(code) + codeHash := crypto.Keccak256(code) + b := crypto.CreateAddress2(addr, common.HexToHash(salt), codeHash).Bytes() + res, err := t.toBuf(vm, b) + if err != nil { + vm.Interrupt(err) + return nil + } + return res + }) + vm.Set("isPrecompiled", func(v goja.Value) bool { + a, err := t.fromBuf(vm, v, true) + if err != nil { + vm.Interrupt(err) + return false + } + addr := common.BytesToAddress(a) + for _, p := range t.activePrecompiles { + if p == addr { + return true + } + } + return false + }) + vm.Set("slice", func(slice goja.Value, start, end int) goja.Value { + b, err := t.fromBuf(vm, slice, false) + if err != nil { + vm.Interrupt(err) + return nil + } + if start < 0 || start > end || end > len(b) { + vm.Interrupt(fmt.Sprintf("Tracer accessed out of bound memory: available %d, offset %d, size %d", len(b), start, end-start)) + return nil + } + res, err := t.toBuf(vm, b[start:end]) + if err != nil { + vm.Interrupt(err) + return nil + } + return res + }) +} + +// setTypeConverters sets up utilities for converting Go types into those +// suitable for JS consumption. +func (t *jsTracer) setTypeConverters() error { + // Inject bigint logic. + // TODO: To be replaced after goja adds support for native JS bigint. + toBigCode, err := t.vm.RunProgram(bigIntProgram) + if err != nil { + return err + } + // Used to create JS bigint objects from go. + toBigFn, ok := goja.AssertFunction(toBigCode) + if !ok { + return errors.New("failed to bind bigInt func") + } + toBigWrapper := func(vm *goja.Runtime, val string) (goja.Value, error) { + return toBigFn(goja.Undefined(), vm.ToValue(val)) + } + t.toBig = toBigWrapper + // NOTE: We need this workaround to create JS buffers because + // goja doesn't at the moment expose constructors for typed arrays. + // + // Cache uint8ArrayType once to be used every time for less overhead. + uint8ArrayType := t.vm.Get("Uint8Array") + toBufWrapper := func(vm *goja.Runtime, val []byte) (goja.Value, error) { + return toBuf(vm, uint8ArrayType, val) + } + t.toBuf = toBufWrapper + fromBufWrapper := func(vm *goja.Runtime, buf goja.Value, allowString bool) ([]byte, error) { + return fromBuf(vm, uint8ArrayType, buf, allowString) + } + t.fromBuf = fromBufWrapper + return nil +} + +type opObj struct { + vm *goja.Runtime + op vm.OpCode +} + +func (o *opObj) ToNumber() int { + return int(o.op) +} + +func (o *opObj) ToString() string { + return o.op.String() +} + +func (o *opObj) IsPush() bool { + return o.op.IsPush() +} + +func (o *opObj) setupObject() *goja.Object { + obj := o.vm.NewObject() + obj.Set("toNumber", o.vm.ToValue(o.ToNumber)) + obj.Set("toString", o.vm.ToValue(o.ToString)) + obj.Set("isPush", o.vm.ToValue(o.IsPush)) + return obj +} + +type memoryObj struct { + memory *vm.Memory + vm *goja.Runtime + toBig toBigFn + toBuf toBufFn +} + +func (mo *memoryObj) Slice(begin, end int64) goja.Value { + b, err := mo.slice(begin, end) + if err != nil { + mo.vm.Interrupt(err) + return nil + } + res, err := mo.toBuf(mo.vm, b) + if err != nil { + mo.vm.Interrupt(err) + return nil + } + return res +} + +// slice returns the requested range of memory as a byte slice. +func (mo *memoryObj) slice(begin, end int64) ([]byte, error) { + if end == begin { + return []byte{}, nil + } + if end < begin || begin < 0 { + return nil, fmt.Errorf("tracer accessed out of bound memory: offset %d, end %d", begin, end) + } + if mo.memory.Len() < int(end) { + return nil, fmt.Errorf("tracer accessed out of bound memory: available %d, offset %d, size %d", mo.memory.Len(), begin, end-begin) + } + return mo.memory.GetCopy(begin, end-begin), nil +} + +func (mo *memoryObj) GetUint(addr int64) goja.Value { + value, err := mo.getUint(addr) + if err != nil { + mo.vm.Interrupt(err) + return nil + } + res, err := mo.toBig(mo.vm, value.String()) + if err != nil { + mo.vm.Interrupt(err) + return nil + } + return res +} + +// getUint returns the 32 bytes at the specified address interpreted as a uint. +func (mo *memoryObj) getUint(addr int64) (*big.Int, error) { + if mo.memory.Len() < int(addr)+32 || addr < 0 { + return nil, fmt.Errorf("tracer accessed out of bound memory: available %d, offset %d, size %d", mo.memory.Len(), addr, 32) + } + return new(big.Int).SetBytes(mo.memory.GetPtr(addr, 32)), nil +} + +func (mo *memoryObj) Length() int { + return mo.memory.Len() +} + +func (m *memoryObj) setupObject() *goja.Object { + o := m.vm.NewObject() + o.Set("slice", m.vm.ToValue(m.Slice)) + o.Set("getUint", m.vm.ToValue(m.GetUint)) + o.Set("length", m.vm.ToValue(m.Length)) + return o +} + +type stackObj struct { + stack *vm.Stack + vm *goja.Runtime + toBig toBigFn +} + +func (s *stackObj) Peek(idx int) goja.Value { + value, err := s.peek(idx) + if err != nil { + s.vm.Interrupt(err) + return nil + } + res, err := s.toBig(s.vm, value.String()) + if err != nil { + s.vm.Interrupt(err) + return nil + } + return res +} + +// peek returns the nth-from-the-top element of the stack. +func (s *stackObj) peek(idx int) (*big.Int, error) { + if len(s.stack.Data()) <= idx || idx < 0 { + return nil, fmt.Errorf("tracer accessed out of bound stack: size %d, index %d", len(s.stack.Data()), idx) + } + return s.stack.Back(idx).ToBig(), nil +} + +func (s *stackObj) Length() int { + return len(s.stack.Data()) +} + +func (s *stackObj) setupObject() *goja.Object { + o := s.vm.NewObject() + o.Set("peek", s.vm.ToValue(s.Peek)) + o.Set("length", s.vm.ToValue(s.Length)) + return o +} + +type dbObj struct { + db vm.StateDB + vm *goja.Runtime + toBig toBigFn + toBuf toBufFn + fromBuf fromBufFn +} + +func (do *dbObj) GetBalance(addrSlice goja.Value) goja.Value { + a, err := do.fromBuf(do.vm, addrSlice, false) + if err != nil { + do.vm.Interrupt(err) + return nil + } + addr := common.BytesToAddress(a) + value := do.db.GetBalance(addr) + res, err := do.toBig(do.vm, value.String()) + if err != nil { + do.vm.Interrupt(err) + return nil + } + return res +} + +func (do *dbObj) GetNonce(addrSlice goja.Value) uint64 { + a, err := do.fromBuf(do.vm, addrSlice, false) + if err != nil { + do.vm.Interrupt(err) + return 0 + } + addr := common.BytesToAddress(a) + return do.db.GetNonce(addr) +} + +func (do *dbObj) GetCode(addrSlice goja.Value) goja.Value { + a, err := do.fromBuf(do.vm, addrSlice, false) + if err != nil { + do.vm.Interrupt(err) + return nil + } + addr := common.BytesToAddress(a) + code := do.db.GetCode(addr) + res, err := do.toBuf(do.vm, code) + if err != nil { + do.vm.Interrupt(err) + return nil + } + return res +} + +func (do *dbObj) GetState(addrSlice goja.Value, hashSlice goja.Value) goja.Value { + a, err := do.fromBuf(do.vm, addrSlice, false) + if err != nil { + do.vm.Interrupt(err) + return nil + } + addr := common.BytesToAddress(a) + h, err := do.fromBuf(do.vm, hashSlice, false) + if err != nil { + do.vm.Interrupt(err) + return nil + } + hash := common.BytesToHash(h) + state := do.db.GetState(addr, hash).Bytes() + res, err := do.toBuf(do.vm, state) + if err != nil { + do.vm.Interrupt(err) + return nil + } + return res +} + +func (do *dbObj) Exists(addrSlice goja.Value) bool { + a, err := do.fromBuf(do.vm, addrSlice, false) + if err != nil { + do.vm.Interrupt(err) + return false + } + addr := common.BytesToAddress(a) + return do.db.Exist(addr) +} + +func (do *dbObj) setupObject() *goja.Object { + o := do.vm.NewObject() + o.Set("getBalance", do.vm.ToValue(do.GetBalance)) + o.Set("getNonce", do.vm.ToValue(do.GetNonce)) + o.Set("getCode", do.vm.ToValue(do.GetCode)) + o.Set("getState", do.vm.ToValue(do.GetState)) + o.Set("exists", do.vm.ToValue(do.Exists)) + return o +} + +type contractObj struct { + contract *vm.Contract + vm *goja.Runtime + toBig toBigFn + toBuf toBufFn +} + +func (co *contractObj) GetCaller() goja.Value { + caller := co.contract.Caller().Bytes() + res, err := co.toBuf(co.vm, caller) + if err != nil { + co.vm.Interrupt(err) + return nil + } + return res +} + +func (co *contractObj) GetAddress() goja.Value { + addr := co.contract.Address().Bytes() + res, err := co.toBuf(co.vm, addr) + if err != nil { + co.vm.Interrupt(err) + return nil + } + return res +} + +func (co *contractObj) GetValue() goja.Value { + value := co.contract.Value() + res, err := co.toBig(co.vm, value.String()) + if err != nil { + co.vm.Interrupt(err) + return nil + } + return res +} + +func (co *contractObj) GetInput() goja.Value { + input := common.CopyBytes(co.contract.Input) + res, err := co.toBuf(co.vm, input) + if err != nil { + co.vm.Interrupt(err) + return nil + } + return res +} + +func (c *contractObj) setupObject() *goja.Object { + o := c.vm.NewObject() + o.Set("getCaller", c.vm.ToValue(c.GetCaller)) + o.Set("getAddress", c.vm.ToValue(c.GetAddress)) + o.Set("getValue", c.vm.ToValue(c.GetValue)) + o.Set("getInput", c.vm.ToValue(c.GetInput)) + return o +} + +type callframe struct { + vm *goja.Runtime + toBig toBigFn + toBuf toBufFn + + typ string + from common.Address + to common.Address + input []byte + gas uint + value *big.Int +} + +func (f *callframe) GetType() string { + return f.typ +} + +func (f *callframe) GetFrom() goja.Value { + from := f.from.Bytes() + res, err := f.toBuf(f.vm, from) + if err != nil { + f.vm.Interrupt(err) + return nil + } + return res +} + +func (f *callframe) GetTo() goja.Value { + to := f.to.Bytes() + res, err := f.toBuf(f.vm, to) + if err != nil { + f.vm.Interrupt(err) + return nil + } + return res +} + +func (f *callframe) GetInput() goja.Value { + input := f.input + res, err := f.toBuf(f.vm, input) + if err != nil { + f.vm.Interrupt(err) + return nil + } + return res +} + +func (f *callframe) GetGas() uint { + return f.gas +} + +func (f *callframe) GetValue() goja.Value { + if f.value == nil { + return goja.Undefined() + } + res, err := f.toBig(f.vm, f.value.String()) + if err != nil { + f.vm.Interrupt(err) + return nil + } + return res +} + +func (f *callframe) setupObject() *goja.Object { + o := f.vm.NewObject() + o.Set("getType", f.vm.ToValue(f.GetType)) + o.Set("getFrom", f.vm.ToValue(f.GetFrom)) + o.Set("getTo", f.vm.ToValue(f.GetTo)) + o.Set("getInput", f.vm.ToValue(f.GetInput)) + o.Set("getGas", f.vm.ToValue(f.GetGas)) + o.Set("getValue", f.vm.ToValue(f.GetValue)) + return o +} + +type callframeResult struct { + vm *goja.Runtime + toBuf toBufFn + + gasUsed uint + output []byte + err error +} + +func (r *callframeResult) GetGasUsed() uint { + return r.gasUsed +} + +func (r *callframeResult) GetOutput() goja.Value { + res, err := r.toBuf(r.vm, r.output) + if err != nil { + r.vm.Interrupt(err) + return nil + } + return res +} + +func (r *callframeResult) GetError() goja.Value { + if r.err != nil { + return r.vm.ToValue(r.err.Error()) + } + return goja.Undefined() +} + +func (r *callframeResult) setupObject() *goja.Object { + o := r.vm.NewObject() + o.Set("getGasUsed", r.vm.ToValue(r.GetGasUsed)) + o.Set("getOutput", r.vm.ToValue(r.GetOutput)) + o.Set("getError", r.vm.ToValue(r.GetError)) + return o +} + +type steplog struct { + vm *goja.Runtime + + op *opObj + memory *memoryObj + stack *stackObj + contract *contractObj + + pc uint + gas uint + cost uint + depth uint + refund uint + err error +} + +func (l *steplog) GetPC() uint { + return l.pc +} + +func (l *steplog) GetGas() uint { + return l.gas +} + +func (l *steplog) GetCost() uint { + return l.cost +} + +func (l *steplog) GetDepth() uint { + return l.depth +} + +func (l *steplog) GetRefund() uint { + return l.refund +} + +func (l *steplog) GetError() goja.Value { + if l.err != nil { + return l.vm.ToValue(l.err.Error()) + } + return goja.Undefined() +} + +func (l *steplog) setupObject() *goja.Object { + o := l.vm.NewObject() + // Setup basic fields. + o.Set("getPC", l.vm.ToValue(l.GetPC)) + o.Set("getGas", l.vm.ToValue(l.GetGas)) + o.Set("getCost", l.vm.ToValue(l.GetCost)) + o.Set("getDepth", l.vm.ToValue(l.GetDepth)) + o.Set("getRefund", l.vm.ToValue(l.GetRefund)) + o.Set("getError", l.vm.ToValue(l.GetError)) + // Setup nested objects. + o.Set("op", l.op.setupObject()) + o.Set("stack", l.stack.setupObject()) + o.Set("memory", l.memory.setupObject()) + o.Set("contract", l.contract.setupObject()) + return o +} diff --git a/x/evm/tracers/js/internal/tracers/4byte_tracer_legacy.js b/x/evm/tracers/js/internal/tracers/4byte_tracer_legacy.js new file mode 100644 index 00000000..e4714b8b --- /dev/null +++ b/x/evm/tracers/js/internal/tracers/4byte_tracer_legacy.js @@ -0,0 +1,86 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// 4byteTracer searches for 4byte-identifiers, and collects them for post-processing. +// It collects the methods identifiers along with the size of the supplied data, so +// a reversed signature can be matched against the size of the data. +// +// Example: +// > debug.traceTransaction( "0x214e597e35da083692f5386141e69f47e973b2c56e7a8073b1ea08fd7571e9de", {tracer: "4byteTracer"}) +// { +// 0x27dc297e-128: 1, +// 0x38cc4831-0: 2, +// 0x524f3889-96: 1, +// 0xadf59f99-288: 1, +// 0xc281d19e-0: 1 +// } +{ + // ids aggregates the 4byte ids found. + ids : {}, + + // callType returns 'false' for non-calls, or the peek-index for the first param + // after 'value', i.e. meminstart. + callType: function(opstr){ + switch(opstr){ + case "CALL": case "CALLCODE": + // gas, addr, val, memin, meminsz, memout, memoutsz + return 3; // stack ptr to memin + + case "DELEGATECALL": case "STATICCALL": + // gas, addr, memin, meminsz, memout, memoutsz + return 2; // stack ptr to memin + } + return false; + }, + + // store save the given identifier and datasize. + store: function(id, size){ + var key = "" + toHex(id) + "-" + size; + this.ids[key] = this.ids[key] + 1 || 1; + }, + + // step is invoked for every opcode that the VM executes. + step: function(log, db) { + // Skip any opcodes that are not internal calls + var ct = this.callType(log.op.toString()); + if (!ct) { + return; + } + // Skip any pre-compile invocations, those are just fancy opcodes + if (isPrecompiled(toAddress(log.stack.peek(1).toString(16)))) { + return; + } + // Gather internal call details + var inSz = log.stack.peek(ct + 1).valueOf(); + if (inSz >= 4) { + var inOff = log.stack.peek(ct).valueOf(); + this.store(log.memory.slice(inOff, inOff + 4), inSz-4); + } + }, + + // fault is invoked when the actual execution of an opcode fails. + fault: function(log, db) { }, + + // result is invoked when all the opcodes have been iterated over and returns + // the final result of the tracing. + result: function(ctx) { + // Save the outer calldata also + if (ctx.input.length >= 4) { + this.store(slice(ctx.input, 0, 4), ctx.input.length-4) + } + return this.ids; + }, +} diff --git a/x/evm/tracers/js/internal/tracers/bigram_tracer.js b/x/evm/tracers/js/internal/tracers/bigram_tracer.js new file mode 100644 index 00000000..421c360a --- /dev/null +++ b/x/evm/tracers/js/internal/tracers/bigram_tracer.js @@ -0,0 +1,47 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +{ + // hist is the counters of opcode bigrams + hist: {}, + // lastOp is last operation + lastOp: '', + // execution depth of last op + lastDepth: 0, + // step is invoked for every opcode that the VM executes. + step: function(log, db) { + var op = log.op.toString(); + var depth = log.getDepth(); + if (depth == this.lastDepth){ + var key = this.lastOp+'-'+op; + if (this.hist[key]){ + this.hist[key]++; + } + else { + this.hist[key] = 1; + } + } + this.lastOp = op; + this.lastDepth = depth; + }, + // fault is invoked when the actual execution of an opcode fails. + fault: function(log, db) {}, + // result is invoked when all the opcodes have been iterated over and returns + // the final result of the tracing. + result: function(ctx) { + return this.hist; + }, +} diff --git a/x/evm/tracers/js/internal/tracers/call_tracer_legacy.js b/x/evm/tracers/js/internal/tracers/call_tracer_legacy.js new file mode 100644 index 00000000..3ca73777 --- /dev/null +++ b/x/evm/tracers/js/internal/tracers/call_tracer_legacy.js @@ -0,0 +1,252 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// callTracer is a full blown transaction tracer that extracts and reports all +// the internal calls made by a transaction, along with any useful information. +{ + // callstack is the current recursive call stack of the EVM execution. + callstack: [{}], + + // descended tracks whether we've just descended from an outer transaction into + // an inner call. + descended: false, + + // step is invoked for every opcode that the VM executes. + step: function(log, db) { + // Capture any errors immediately + var error = log.getError(); + if (error !== undefined) { + this.fault(log, db); + return; + } + // We only care about system opcodes, faster if we pre-check once + var syscall = (log.op.toNumber() & 0xf0) == 0xf0; + if (syscall) { + var op = log.op.toString(); + } + // If a new contract is being created, add to the call stack + if (syscall && (op == 'CREATE' || op == "CREATE2")) { + var inOff = log.stack.peek(1).valueOf(); + var inEnd = inOff + log.stack.peek(2).valueOf(); + + // Assemble the internal call report and store for completion + var call = { + type: op, + from: toHex(log.contract.getAddress()), + input: toHex(log.memory.slice(inOff, inEnd)), + gasIn: log.getGas(), + gasCost: log.getCost(), + value: '0x' + log.stack.peek(0).toString(16) + }; + this.callstack.push(call); + this.descended = true + return; + } + // If a contract is being self destructed, gather that as a subcall too + if (syscall && op == 'SELFDESTRUCT') { + var left = this.callstack.length; + if (this.callstack[left-1].calls === undefined) { + this.callstack[left-1].calls = []; + } + this.callstack[left-1].calls.push({ + type: op, + from: toHex(log.contract.getAddress()), + to: toHex(toAddress(log.stack.peek(0).toString(16))), + gasIn: log.getGas(), + gasCost: log.getCost(), + value: '0x' + db.getBalance(log.contract.getAddress()).toString(16) + }); + return + } + // If a new method invocation is being done, add to the call stack + if (syscall && (op == 'CALL' || op == 'CALLCODE' || op == 'DELEGATECALL' || op == 'STATICCALL')) { + // Skip any pre-compile invocations, those are just fancy opcodes + var to = toAddress(log.stack.peek(1).toString(16)); + if (isPrecompiled(to)) { + return + } + var off = (op == 'DELEGATECALL' || op == 'STATICCALL' ? 0 : 1); + + var inOff = log.stack.peek(2 + off).valueOf(); + var inEnd = inOff + log.stack.peek(3 + off).valueOf(); + + // Assemble the internal call report and store for completion + var call = { + type: op, + from: toHex(log.contract.getAddress()), + to: toHex(to), + input: toHex(log.memory.slice(inOff, inEnd)), + gasIn: log.getGas(), + gasCost: log.getCost(), + outOff: log.stack.peek(4 + off).valueOf(), + outLen: log.stack.peek(5 + off).valueOf() + }; + if (op != 'DELEGATECALL' && op != 'STATICCALL') { + call.value = '0x' + log.stack.peek(2).toString(16); + } + this.callstack.push(call); + this.descended = true + return; + } + // If we've just descended into an inner call, retrieve it's true allowance. We + // need to extract if from within the call as there may be funky gas dynamics + // with regard to requested and actually given gas (2300 stipend, 63/64 rule). + if (this.descended) { + if (log.getDepth() >= this.callstack.length) { + this.callstack[this.callstack.length - 1].gas = log.getGas(); + } else { + // TODO(karalabe): The call was made to a plain account. We currently don't + // have access to the true gas amount inside the call and so any amount will + // mostly be wrong since it depends on a lot of input args. Skip gas for now. + } + this.descended = false; + } + // If an existing call is returning, pop off the call stack + if (syscall && op == 'REVERT') { + this.callstack[this.callstack.length - 1].error = "execution reverted"; + return; + } + if (log.getDepth() == this.callstack.length - 1) { + // Pop off the last call and get the execution results + var call = this.callstack.pop(); + + if (call.type == 'CREATE' || call.type == "CREATE2") { + // If the call was a CREATE, retrieve the contract address and output code + call.gasUsed = '0x' + bigInt(call.gasIn - call.gasCost - log.getGas()).toString(16); + delete call.gasIn; delete call.gasCost; + + var ret = log.stack.peek(0); + if (!ret.equals(0)) { + call.to = toHex(toAddress(ret.toString(16))); + call.output = toHex(db.getCode(toAddress(ret.toString(16)))); + } else if (call.error === undefined) { + call.error = "internal failure"; // TODO(karalabe): surface these faults somehow + } + } else { + // If the call was a contract call, retrieve the gas usage and output + if (call.gas !== undefined) { + call.gasUsed = '0x' + bigInt(call.gasIn - call.gasCost + call.gas - log.getGas()).toString(16); + } + var ret = log.stack.peek(0); + if (!ret.equals(0)) { + call.output = toHex(log.memory.slice(call.outOff, call.outOff + call.outLen)); + } else if (call.error === undefined) { + call.error = "internal failure"; // TODO(karalabe): surface these faults somehow + } + delete call.gasIn; delete call.gasCost; + delete call.outOff; delete call.outLen; + } + if (call.gas !== undefined) { + call.gas = '0x' + bigInt(call.gas).toString(16); + } + // Inject the call into the previous one + var left = this.callstack.length; + if (this.callstack[left-1].calls === undefined) { + this.callstack[left-1].calls = []; + } + this.callstack[left-1].calls.push(call); + } + }, + + // fault is invoked when the actual execution of an opcode fails. + fault: function(log, db) { + // If the topmost call already reverted, don't handle the additional fault again + if (this.callstack[this.callstack.length - 1].error !== undefined) { + return; + } + // Pop off the just failed call + var call = this.callstack.pop(); + call.error = log.getError(); + + // Consume all available gas and clean any leftovers + if (call.gas !== undefined) { + call.gas = '0x' + bigInt(call.gas).toString(16); + call.gasUsed = call.gas + } + delete call.gasIn; delete call.gasCost; + delete call.outOff; delete call.outLen; + + // Flatten the failed call into its parent + var left = this.callstack.length; + if (left > 0) { + if (this.callstack[left-1].calls === undefined) { + this.callstack[left-1].calls = []; + } + this.callstack[left-1].calls.push(call); + return; + } + // Last call failed too, leave it in the stack + this.callstack.push(call); + }, + + // result is invoked when all the opcodes have been iterated over and returns + // the final result of the tracing. + result: function(ctx, db) { + var result = { + type: ctx.type, + from: toHex(ctx.from), + to: toHex(ctx.to), + value: '0x' + ctx.value.toString(16), + gas: '0x' + bigInt(ctx.gas).toString(16), + gasUsed: '0x' + bigInt(ctx.gasUsed).toString(16), + input: toHex(ctx.input), + output: toHex(ctx.output), + time: ctx.time, + }; + if (this.callstack[0].calls !== undefined) { + result.calls = this.callstack[0].calls; + } + if (this.callstack[0].error !== undefined) { + result.error = this.callstack[0].error; + } else if (ctx.error !== undefined) { + result.error = ctx.error; + } + if (result.error !== undefined && (result.error !== "execution reverted" || result.output ==="0x")) { + delete result.output; + } + return this.finalize(result); + }, + + // finalize recreates a call object using the final desired field oder for json + // serialization. This is a nicety feature to pass meaningfully ordered results + // to users who don't interpret it, just display it. + finalize: function(call) { + var sorted = { + type: call.type, + from: call.from, + to: call.to, + value: call.value, + gas: call.gas, + gasUsed: call.gasUsed, + input: call.input, + output: call.output, + error: call.error, + time: call.time, + calls: call.calls, + } + for (var key in sorted) { + if (sorted[key] === undefined) { + delete sorted[key]; + } + } + if (sorted.calls !== undefined) { + for (var i=0; i. + +// evmdisTracer returns sufficient information from a trace to perform evmdis-style +// disassembly. +{ + stack: [{ops: []}], + + npushes: {0: 0, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1, 10: 1, 11: 1, 16: 1, 17: 1, 18: 1, 19: 1, 20: 1, 21: 1, 22: 1, 23: 1, 24: 1, 25: 1, 26: 1, 32: 1, 48: 1, 49: 1, 50: 1, 51: 1, 52: 1, 53: 1, 54: 1, 55: 0, 56: 1, 57: 0, 58: 1, 59: 1, 60: 0, 64: 1, 65: 1, 66: 1, 67: 1, 68: 1, 69: 1, 80: 0, 81: 1, 82: 0, 83: 0, 84: 1, 85: 0, 86: 0, 87: 0, 88: 1, 89: 1, 90: 1, 91: 0, 96: 1, 97: 1, 98: 1, 99: 1, 100: 1, 101: 1, 102: 1, 103: 1, 104: 1, 105: 1, 106: 1, 107: 1, 108: 1, 109: 1, 110: 1, 111: 1, 112: 1, 113: 1, 114: 1, 115: 1, 116: 1, 117: 1, 118: 1, 119: 1, 120: 1, 121: 1, 122: 1, 123: 1, 124: 1, 125: 1, 126: 1, 127: 1, 128: 2, 129: 3, 130: 4, 131: 5, 132: 6, 133: 7, 134: 8, 135: 9, 136: 10, 137: 11, 138: 12, 139: 13, 140: 14, 141: 15, 142: 16, 143: 17, 144: 2, 145: 3, 146: 4, 147: 5, 148: 6, 149: 7, 150: 8, 151: 9, 152: 10, 153: 11, 154: 12, 155: 13, 156: 14, 157: 15, 158: 16, 159: 17, 160: 0, 161: 0, 162: 0, 163: 0, 164: 0, 240: 1, 241: 1, 242: 1, 243: 0, 244: 0, 255: 0}, + + // result is invoked when all the opcodes have been iterated over and returns + // the final result of the tracing. + result: function() { return this.stack[0].ops; }, + + // fault is invoked when the actual execution of an opcode fails. + fault: function(log, db) { }, + + // step is invoked for every opcode that the VM executes. + step: function(log, db) { + var frame = this.stack[this.stack.length - 1]; + + var error = log.getError(); + if (error) { + frame["error"] = error; + } else if (log.getDepth() == this.stack.length) { + opinfo = { + op: log.op.toNumber(), + depth : log.getDepth(), + result: [], + }; + if (frame.ops.length > 0) { + var prevop = frame.ops[frame.ops.length - 1]; + for(var i = 0; i < this.npushes[prevop.op]; i++) + prevop.result.push(log.stack.peek(i).toString(16)); + } + switch(log.op.toString()) { + case "CALL": case "CALLCODE": + var instart = log.stack.peek(3).valueOf(); + var insize = log.stack.peek(4).valueOf(); + opinfo["gas"] = log.stack.peek(0).valueOf(); + opinfo["to"] = log.stack.peek(1).toString(16); + opinfo["value"] = log.stack.peek(2).toString(); + opinfo["input"] = log.memory.slice(instart, instart + insize); + opinfo["error"] = null; + opinfo["return"] = null; + opinfo["ops"] = []; + this.stack.push(opinfo); + break; + case "DELEGATECALL": case "STATICCALL": + var instart = log.stack.peek(2).valueOf(); + var insize = log.stack.peek(3).valueOf(); + opinfo["op"] = log.op.toString(); + opinfo["gas"] = log.stack.peek(0).valueOf(); + opinfo["to"] = log.stack.peek(1).toString(16); + opinfo["input"] = log.memory.slice(instart, instart + insize); + opinfo["error"] = null; + opinfo["return"] = null; + opinfo["ops"] = []; + this.stack.push(opinfo); + break; + case "RETURN": case "REVERT": + var out = log.stack.peek(0).valueOf(); + var outsize = log.stack.peek(1).valueOf(); + frame.return = log.memory.slice(out, out + outsize); + break; + case "STOP": case "SELFDESTRUCT": + frame.return = log.memory.slice(0, 0); + break; + case "JUMPDEST": + opinfo["pc"] = log.getPC(); + } + if(log.op.isPush()) { + opinfo["len"] = log.op.toNumber() - 0x5e; + } + frame.ops.push(opinfo); + } else { + this.stack = this.stack.slice(0, log.getDepth()); + } + } +} diff --git a/x/evm/tracers/js/internal/tracers/noop_tracer_legacy.js b/x/evm/tracers/js/internal/tracers/noop_tracer_legacy.js new file mode 100644 index 00000000..fe7ddc85 --- /dev/null +++ b/x/evm/tracers/js/internal/tracers/noop_tracer_legacy.js @@ -0,0 +1,29 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// noopTracer is just the barebone boilerplate code required from a JavaScript +// object to be usable as a transaction tracer. +{ + // step is invoked for every opcode that the VM executes. + step: function(log, db) { }, + + // fault is invoked when the actual execution of an opcode fails. + fault: function(log, db) { }, + + // result is invoked when all the opcodes have been iterated over and returns + // the final result of the tracing. + result: function(ctx, db) { return {}; } +} diff --git a/x/evm/tracers/js/internal/tracers/opcount_tracer.js b/x/evm/tracers/js/internal/tracers/opcount_tracer.js new file mode 100644 index 00000000..f7984c74 --- /dev/null +++ b/x/evm/tracers/js/internal/tracers/opcount_tracer.js @@ -0,0 +1,32 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// opcountTracer is a sample tracer that just counts the number of instructions +// executed by the EVM before the transaction terminated. +{ + // count tracks the number of EVM instructions executed. + count: 0, + + // step is invoked for every opcode that the VM executes. + step: function(log, db) { this.count++ }, + + // fault is invoked when the actual execution of an opcode fails. + fault: function(log, db) { }, + + // result is invoked when all the opcodes have been iterated over and returns + // the final result of the tracing. + result: function(ctx, db) { return this.count } +} diff --git a/x/evm/tracers/js/internal/tracers/prestate_tracer_legacy.js b/x/evm/tracers/js/internal/tracers/prestate_tracer_legacy.js new file mode 100644 index 00000000..77f25209 --- /dev/null +++ b/x/evm/tracers/js/internal/tracers/prestate_tracer_legacy.js @@ -0,0 +1,115 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// prestateTracer outputs sufficient information to create a local execution of +// the transaction from a custom assembled genesis block. +{ + // prestate is the genesis that we're building. + prestate: null, + + // lookupAccount injects the specified account into the prestate object. + lookupAccount: function(addr, db){ + var acc = toHex(addr); + if (this.prestate[acc] === undefined) { + this.prestate[acc] = { + balance: '0x' + db.getBalance(addr).toString(16), + nonce: db.getNonce(addr), + code: toHex(db.getCode(addr)), + storage: {} + }; + } + }, + + // lookupStorage injects the specified storage entry of the given account into + // the prestate object. + lookupStorage: function(addr, key, db){ + var acc = toHex(addr); + var idx = toHex(key); + + if (this.prestate[acc].storage[idx] === undefined) { + this.prestate[acc].storage[idx] = toHex(db.getState(addr, key)); + } + }, + + // result is invoked when all the opcodes have been iterated over and returns + // the final result of the tracing. + result: function(ctx, db) { + if (this.prestate === null) { + this.prestate = {}; + // If tx is transfer-only, the recipient account + // hasn't been populated. + this.lookupAccount(ctx.to, db); + } + + // At this point, we need to deduct the 'value' from the + // outer transaction, and move it back to the origin + this.lookupAccount(ctx.from, db); + + var fromBal = bigInt(this.prestate[toHex(ctx.from)].balance.slice(2), 16); + var toBal = bigInt(this.prestate[toHex(ctx.to)].balance.slice(2), 16); + + this.prestate[toHex(ctx.to)].balance = '0x'+toBal.subtract(ctx.value).toString(16); + this.prestate[toHex(ctx.from)].balance = '0x'+fromBal.add(ctx.value).add((ctx.gasUsed + ctx.intrinsicGas) * ctx.gasPrice).toString(16); + + // Decrement the caller's nonce, and remove empty create targets + this.prestate[toHex(ctx.from)].nonce--; + if (ctx.type == 'CREATE') { + // We can blibdly delete the contract prestate, as any existing state would + // have caused the transaction to be rejected as invalid in the first place. + delete this.prestate[toHex(ctx.to)]; + } + // Return the assembled allocations (prestate) + return this.prestate; + }, + + // step is invoked for every opcode that the VM executes. + step: function(log, db) { + // Add the current account if we just started tracing + if (this.prestate === null){ + this.prestate = {}; + // Balance will potentially be wrong here, since this will include the value + // sent along with the message. We fix that in 'result()'. + this.lookupAccount(log.contract.getAddress(), db); + } + // Whenever new state is accessed, add it to the prestate + switch (log.op.toString()) { + case "EXTCODECOPY": case "EXTCODESIZE": case "EXTCODEHASH": case "BALANCE": + this.lookupAccount(toAddress(log.stack.peek(0).toString(16)), db); + break; + case "CREATE": + var from = log.contract.getAddress(); + this.lookupAccount(toContract(from, db.getNonce(from)), db); + break; + case "CREATE2": + var from = log.contract.getAddress(); + // stack: salt, size, offset, endowment + var offset = log.stack.peek(1).valueOf() + var size = log.stack.peek(2).valueOf() + var end = offset + size + this.lookupAccount(toContract2(from, log.stack.peek(3).toString(16), log.memory.slice(offset, end)), db); + break; + case "CALL": case "CALLCODE": case "DELEGATECALL": case "STATICCALL": + this.lookupAccount(toAddress(log.stack.peek(1).toString(16)), db); + break; + case 'SSTORE':case 'SLOAD': + this.lookupStorage(log.contract.getAddress(), toWord(log.stack.peek(0).toString(16)), db); + break; + } + }, + + // fault is invoked when the actual execution of an opcode fails. + fault: function(log, db) {} +} diff --git a/x/evm/tracers/js/internal/tracers/tracers.go b/x/evm/tracers/js/internal/tracers/tracers.go new file mode 100644 index 00000000..6547f1b0 --- /dev/null +++ b/x/evm/tracers/js/internal/tracers/tracers.go @@ -0,0 +1,59 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package tracers contains the actual JavaScript tracer assets. +package tracers + +import ( + "embed" + "io/fs" + "strings" + "unicode" +) + +//go:embed *.js +var files embed.FS + +// Load reads the built-in JS tracer files embedded in the binary and +// returns a mapping of tracer name to source. +func Load() (map[string]string, error) { + var assetTracers = make(map[string]string) + err := fs.WalkDir(files, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if d.IsDir() { + return nil + } + b, err := fs.ReadFile(files, path) + if err != nil { + return err + } + name := camel(strings.TrimSuffix(path, ".js")) + assetTracers[name] = string(b) + return nil + }) + return assetTracers, err +} + +// camel converts a snake cased input string into a camel cased output. +func camel(str string) string { + pieces := strings.Split(str, "_") + for i := 1; i < len(pieces); i++ { + pieces[i] = string(unicode.ToUpper(rune(pieces[i][0]))) + pieces[i][1:] + } + return strings.Join(pieces, "") +} diff --git a/x/evm/tracers/js/internal/tracers/trigram_tracer.js b/x/evm/tracers/js/internal/tracers/trigram_tracer.js new file mode 100644 index 00000000..8756490d --- /dev/null +++ b/x/evm/tracers/js/internal/tracers/trigram_tracer.js @@ -0,0 +1,49 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +{ + // hist is the map of trigram counters + hist: {}, + // lastOp is last operation + lastOps: ['',''], + lastDepth: 0, + // step is invoked for every opcode that the VM executes. + step: function(log, db) { + var depth = log.getDepth(); + if (depth != this.lastDepth){ + this.lastOps = ['','']; + this.lastDepth = depth; + return; + } + var op = log.op.toString(); + var key = this.lastOps[0]+'-'+this.lastOps[1]+'-'+op; + if (this.hist[key]){ + this.hist[key]++; + } + else { + this.hist[key] = 1; + } + this.lastOps[0] = this.lastOps[1]; + this.lastOps[1] = op; + }, + // fault is invoked when the actual execution of an opcode fails. + fault: function(log, db) {}, + // result is invoked when all the opcodes have been iterated over and returns + // the final result of the tracing. + result: function(ctx) { + return this.hist; + }, +} diff --git a/x/evm/tracers/js/internal/tracers/unigram_tracer.js b/x/evm/tracers/js/internal/tracers/unigram_tracer.js new file mode 100644 index 00000000..51107d8f --- /dev/null +++ b/x/evm/tracers/js/internal/tracers/unigram_tracer.js @@ -0,0 +1,41 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +{ + // hist is the map of opcodes to counters + hist: {}, + // nops counts number of ops + nops: 0, + // step is invoked for every opcode that the VM executes. + step: function(log, db) { + var op = log.op.toString(); + if (this.hist[op]){ + this.hist[op]++; + } + else { + this.hist[op] = 1; + } + this.nops++; + }, + // fault is invoked when the actual execution of an opcode fails. + fault: function(log, db) {}, + + // result is invoked when all the opcodes have been iterated over and returns + // the final result of the tracing. + result: function(ctx) { + return this.hist; + }, +} diff --git a/x/evm/tracers/native/4byte.go b/x/evm/tracers/native/4byte.go new file mode 100644 index 00000000..34e608bf --- /dev/null +++ b/x/evm/tracers/native/4byte.go @@ -0,0 +1,152 @@ +// Copyright 2021 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package native + +import ( + "encoding/json" + "math/big" + "strconv" + "sync/atomic" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/tracers" +) + +func init() { + register("4byteTracer", newFourByteTracer) +} + +// fourByteTracer searches for 4byte-identifiers, and collects them for post-processing. +// It collects the methods identifiers along with the size of the supplied data, so +// a reversed signature can be matched against the size of the data. +// +// Example: +// > debug.traceTransaction( "0x214e597e35da083692f5386141e69f47e973b2c56e7a8073b1ea08fd7571e9de", {tracer: "4byteTracer"}) +// { +// 0x27dc297e-128: 1, +// 0x38cc4831-0: 2, +// 0x524f3889-96: 1, +// 0xadf59f99-288: 1, +// 0xc281d19e-0: 1 +// } +type fourByteTracer struct { + env *vm.EVM + ids map[string]int // ids aggregates the 4byte ids found + interrupt uint32 // Atomic flag to signal execution interruption + reason error // Textual reason for the interruption + activePrecompiles []common.Address // Updated on CaptureStart based on given rules +} + +// newFourByteTracer returns a native go tracer which collects +// 4 byte-identifiers of a tx, and implements vm.EVMLogger. +func newFourByteTracer(ctx *tracers.Context, _ json.RawMessage) (tracers.Tracer, error) { + t := &fourByteTracer{ + ids: make(map[string]int), + } + return t, nil +} + +// isPrecompiled returns whether the addr is a precompile. Logic borrowed from newJsTracer in eth/tracers/js/tracer.go +func (t *fourByteTracer) isPrecompiled(addr common.Address) bool { + for _, p := range t.activePrecompiles { + if p == addr { + return true + } + } + return false +} + +// store saves the given identifier and datasize. +func (t *fourByteTracer) store(id []byte, size int) { + key := bytesToHex(id) + "-" + strconv.Itoa(size) + t.ids[key] += 1 +} + +// CaptureStart implements the EVMLogger interface to initialize the tracing operation. +func (t *fourByteTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { + t.env = env + + // Update list of precompiles based on current block + rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil) + t.activePrecompiles = vm.ActivePrecompiles(rules) + + // Save the outer calldata also + if len(input) >= 4 { + t.store(input[0:4], len(input)-4) + } +} + +// CaptureState implements the EVMLogger interface to trace a single step of VM execution. +func (t *fourByteTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { +} + +// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *fourByteTracer) CaptureEnter(op vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + // Skip if tracing was interrupted + if atomic.LoadUint32(&t.interrupt) > 0 { + t.env.Cancel() + return + } + if len(input) < 4 { + return + } + // primarily we want to avoid CREATE/CREATE2/SELFDESTRUCT + if op != vm.DELEGATECALL && op != vm.STATICCALL && + op != vm.CALL && op != vm.CALLCODE { + return + } + // Skip any pre-compile invocations, those are just fancy opcodes + if t.isPrecompiled(to) { + return + } + t.store(input[0:4], len(input)-4) +} + +// CaptureExit is called when EVM exits a scope, even if the scope didn't +// execute any code. +func (t *fourByteTracer) CaptureExit(output []byte, gasUsed uint64, err error) { +} + +// CaptureFault implements the EVMLogger interface to trace an execution fault. +func (t *fourByteTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) { +} + +// CaptureEnd is called after the call finishes to finalize the tracing. +func (t *fourByteTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) { +} + +func (*fourByteTracer) CaptureTxStart(gasLimit uint64) {} + +func (*fourByteTracer) CaptureTxEnd(restGas uint64) {} + +// GetResult returns the json-encoded nested list of call traces, and any +// error arising from the encoding or forceful termination (via `Stop`). +func (t *fourByteTracer) GetResult() (json.RawMessage, error) { + res, err := json.Marshal(t.ids) + if err != nil { + return nil, err + } + return res, t.reason +} + +// Stop terminates execution of the tracer at the first opportune moment. +func (t *fourByteTracer) Stop(err error) { + t.reason = err + atomic.StoreUint32(&t.interrupt, 1) +} diff --git a/x/evm/tracers/native/call.go b/x/evm/tracers/native/call.go new file mode 100644 index 00000000..7af0e658 --- /dev/null +++ b/x/evm/tracers/native/call.go @@ -0,0 +1,202 @@ +// Copyright 2021 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package native + +import ( + "encoding/json" + "errors" + "math/big" + "strconv" + "strings" + "sync/atomic" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/tracers" +) + +func init() { + register("callTracer", newCallTracer) +} + +type callFrame struct { + Type string `json:"type"` + From string `json:"from"` + To string `json:"to,omitempty"` + Value string `json:"value,omitempty"` + Gas string `json:"gas"` + GasUsed string `json:"gasUsed"` + Input string `json:"input"` + Output string `json:"output,omitempty"` + Error string `json:"error,omitempty"` + Calls []callFrame `json:"calls,omitempty"` +} + +type callTracer struct { + env *vm.EVM + callstack []callFrame + config callTracerConfig + interrupt uint32 // Atomic flag to signal execution interruption + reason error // Textual reason for the interruption +} + +type callTracerConfig struct { + OnlyTopCall bool `json:"onlyTopCall"` // If true, call tracer won't collect any subcalls +} + +// newCallTracer returns a native go tracer which tracks +// call frames of a tx, and implements vm.EVMLogger. +func newCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) { + var config callTracerConfig + if cfg != nil { + if err := json.Unmarshal(cfg, &config); err != nil { + return nil, err + } + } + // First callframe contains tx context info + // and is populated on start and end. + return &callTracer{callstack: make([]callFrame, 1), config: config}, nil +} + +// CaptureStart implements the EVMLogger interface to initialize the tracing operation. +func (t *callTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { + t.env = env + t.callstack[0] = callFrame{ + Type: "CALL", + From: addrToHex(from), + To: addrToHex(to), + Input: bytesToHex(input), + Gas: uintToHex(gas), + Value: bigToHex(value), + } + if create { + t.callstack[0].Type = "CREATE" + } +} + +// CaptureEnd is called after the call finishes to finalize the tracing. +func (t *callTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) { + t.callstack[0].GasUsed = uintToHex(gasUsed) + if err != nil { + t.callstack[0].Error = err.Error() + if err.Error() == "execution reverted" && len(output) > 0 { + t.callstack[0].Output = bytesToHex(output) + } + } else { + t.callstack[0].Output = bytesToHex(output) + } +} + +// CaptureState implements the EVMLogger interface to trace a single step of VM execution. +func (t *callTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { +} + +// CaptureFault implements the EVMLogger interface to trace an execution fault. +func (t *callTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) { +} + +// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *callTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + if t.config.OnlyTopCall { + return + } + // Skip if tracing was interrupted + if atomic.LoadUint32(&t.interrupt) > 0 { + t.env.Cancel() + return + } + + call := callFrame{ + Type: typ.String(), + From: addrToHex(from), + To: addrToHex(to), + Input: bytesToHex(input), + Gas: uintToHex(gas), + Value: bigToHex(value), + } + t.callstack = append(t.callstack, call) +} + +// CaptureExit is called when EVM exits a scope, even if the scope didn't +// execute any code. +func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error) { + if t.config.OnlyTopCall { + return + } + size := len(t.callstack) + if size <= 1 { + return + } + // pop call + call := t.callstack[size-1] + t.callstack = t.callstack[:size-1] + size -= 1 + + call.GasUsed = uintToHex(gasUsed) + if err == nil { + call.Output = bytesToHex(output) + } else { + call.Error = err.Error() + if call.Type == "CREATE" || call.Type == "CREATE2" { + call.To = "" + } + } + t.callstack[size-1].Calls = append(t.callstack[size-1].Calls, call) +} + +func (*callTracer) CaptureTxStart(gasLimit uint64) {} + +func (*callTracer) CaptureTxEnd(restGas uint64) {} + +// GetResult returns the json-encoded nested list of call traces, and any +// error arising from the encoding or forceful termination (via `Stop`). +func (t *callTracer) GetResult() (json.RawMessage, error) { + if len(t.callstack) != 1 { + return nil, errors.New("incorrect number of top-level calls") + } + res, err := json.Marshal(t.callstack[0]) + if err != nil { + return nil, err + } + return json.RawMessage(res), t.reason +} + +// Stop terminates execution of the tracer at the first opportune moment. +func (t *callTracer) Stop(err error) { + t.reason = err + atomic.StoreUint32(&t.interrupt, 1) +} + +func bytesToHex(s []byte) string { + return "0x" + common.Bytes2Hex(s) +} + +func bigToHex(n *big.Int) string { + if n == nil { + return "" + } + return "0x" + n.Text(16) +} + +func uintToHex(n uint64) string { + return "0x" + strconv.FormatUint(n, 16) +} + +func addrToHex(a common.Address) string { + return strings.ToLower(a.Hex()) +} diff --git a/x/evm/tracers/native/noop.go b/x/evm/tracers/native/noop.go new file mode 100644 index 00000000..c252b240 --- /dev/null +++ b/x/evm/tracers/native/noop.go @@ -0,0 +1,78 @@ +// Copyright 2021 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package native + +import ( + "encoding/json" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/tracers" +) + +func init() { + register("noopTracer", newNoopTracer) +} + +// noopTracer is a go implementation of the Tracer interface which +// performs no action. It's mostly useful for testing purposes. +type noopTracer struct{} + +// newNoopTracer returns a new noop tracer. +func newNoopTracer(ctx *tracers.Context, _ json.RawMessage) (tracers.Tracer, error) { + return &noopTracer{}, nil +} + +// CaptureStart implements the EVMLogger interface to initialize the tracing operation. +func (t *noopTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { +} + +// CaptureEnd is called after the call finishes to finalize the tracing. +func (t *noopTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) { +} + +// CaptureState implements the EVMLogger interface to trace a single step of VM execution. +func (t *noopTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { +} + +// CaptureFault implements the EVMLogger interface to trace an execution fault. +func (t *noopTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) { +} + +// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *noopTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { +} + +// CaptureExit is called when EVM exits a scope, even if the scope didn't +// execute any code. +func (t *noopTracer) CaptureExit(output []byte, gasUsed uint64, err error) { +} + +func (*noopTracer) CaptureTxStart(gasLimit uint64) {} + +func (*noopTracer) CaptureTxEnd(restGas uint64) {} + +// GetResult returns an empty json object. +func (t *noopTracer) GetResult() (json.RawMessage, error) { + return json.RawMessage(`{}`), nil +} + +// Stop terminates execution of the tracer at the first opportune moment. +func (t *noopTracer) Stop(err error) { +} diff --git a/x/evm/tracers/native/prestate.go b/x/evm/tracers/native/prestate.go new file mode 100644 index 00000000..b513f383 --- /dev/null +++ b/x/evm/tracers/native/prestate.go @@ -0,0 +1,178 @@ +// Copyright 2022 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package native + +import ( + "encoding/json" + "math/big" + "sync/atomic" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth/tracers" +) + +func init() { + register("prestateTracer", newPrestateTracer) +} + +type prestate = map[common.Address]*account +type account struct { + Balance string `json:"balance"` + Nonce uint64 `json:"nonce"` + Code string `json:"code"` + Storage map[common.Hash]common.Hash `json:"storage"` +} + +type prestateTracer struct { + env *vm.EVM + prestate prestate + create bool + to common.Address + gasLimit uint64 // Amount of gas bought for the whole tx + interrupt uint32 // Atomic flag to signal execution interruption + reason error // Textual reason for the interruption +} + +func newPrestateTracer(ctx *tracers.Context, _ json.RawMessage) (tracers.Tracer, error) { + // First callframe contains tx context info + // and is populated on start and end. + return &prestateTracer{prestate: prestate{}}, nil +} + +// CaptureStart implements the EVMLogger interface to initialize the tracing operation. +func (t *prestateTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { + t.env = env + t.create = create + t.to = to + + t.lookupAccount(from) + t.lookupAccount(to) + + // The recipient balance includes the value transferred. + toBal := hexutil.MustDecodeBig(t.prestate[to].Balance) + toBal = new(big.Int).Sub(toBal, value) + t.prestate[to].Balance = hexutil.EncodeBig(toBal) + + // The sender balance is after reducing: value and gasLimit. + // We need to re-add them to get the pre-tx balance. + fromBal := hexutil.MustDecodeBig(t.prestate[from].Balance) + gasPrice := env.TxContext.GasPrice + consumedGas := new(big.Int).Mul(gasPrice, new(big.Int).SetUint64(t.gasLimit)) + fromBal.Add(fromBal, new(big.Int).Add(value, consumedGas)) + t.prestate[from].Balance = hexutil.EncodeBig(fromBal) + t.prestate[from].Nonce-- +} + +// CaptureEnd is called after the call finishes to finalize the tracing. +func (t *prestateTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) { + if t.create { + // Exclude created contract. + delete(t.prestate, t.to) + } +} + +// CaptureState implements the EVMLogger interface to trace a single step of VM execution. +func (t *prestateTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { + stack := scope.Stack + stackData := stack.Data() + stackLen := len(stackData) + switch { + case stackLen >= 1 && (op == vm.SLOAD || op == vm.SSTORE): + slot := common.Hash(stackData[stackLen-1].Bytes32()) + t.lookupStorage(scope.Contract.Address(), slot) + case stackLen >= 1 && (op == vm.EXTCODECOPY || op == vm.EXTCODEHASH || op == vm.EXTCODESIZE || op == vm.BALANCE || op == vm.SELFDESTRUCT): + addr := common.Address(stackData[stackLen-1].Bytes20()) + t.lookupAccount(addr) + case stackLen >= 5 && (op == vm.DELEGATECALL || op == vm.CALL || op == vm.STATICCALL || op == vm.CALLCODE): + addr := common.Address(stackData[stackLen-2].Bytes20()) + t.lookupAccount(addr) + case op == vm.CREATE: + addr := scope.Contract.Address() + nonce := t.env.StateDB.GetNonce(addr) + t.lookupAccount(crypto.CreateAddress(addr, nonce)) + case stackLen >= 4 && op == vm.CREATE2: + offset := stackData[stackLen-2] + size := stackData[stackLen-3] + init := scope.Memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64())) + inithash := crypto.Keccak256(init) + salt := stackData[stackLen-4] + t.lookupAccount(crypto.CreateAddress2(scope.Contract.Address(), salt.Bytes32(), inithash)) + } +} + +// CaptureFault implements the EVMLogger interface to trace an execution fault. +func (t *prestateTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) { +} + +// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *prestateTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { +} + +// CaptureExit is called when EVM exits a scope, even if the scope didn't +// execute any code. +func (t *prestateTracer) CaptureExit(output []byte, gasUsed uint64, err error) { +} + +func (t *prestateTracer) CaptureTxStart(gasLimit uint64) { + t.gasLimit = gasLimit +} + +func (t *prestateTracer) CaptureTxEnd(restGas uint64) {} + +// GetResult returns the json-encoded nested list of call traces, and any +// error arising from the encoding or forceful termination (via `Stop`). +func (t *prestateTracer) GetResult() (json.RawMessage, error) { + res, err := json.Marshal(t.prestate) + if err != nil { + return nil, err + } + return json.RawMessage(res), t.reason +} + +// Stop terminates execution of the tracer at the first opportune moment. +func (t *prestateTracer) Stop(err error) { + t.reason = err + atomic.StoreUint32(&t.interrupt, 1) +} + +// lookupAccount fetches details of an account and adds it to the prestate +// if it doesn't exist there. +func (t *prestateTracer) lookupAccount(addr common.Address) { + if _, ok := t.prestate[addr]; ok { + return + } + t.prestate[addr] = &account{ + Balance: bigToHex(t.env.StateDB.GetBalance(addr)), + Nonce: t.env.StateDB.GetNonce(addr), + Code: bytesToHex(t.env.StateDB.GetCode(addr)), + Storage: make(map[common.Hash]common.Hash), + } +} + +// lookupStorage fetches the requested storage slot and adds +// it to the prestate of the given contract. It assumes `lookupAccount` +// has been performed on the contract before. +func (t *prestateTracer) lookupStorage(addr common.Address, key common.Hash) { + if _, ok := t.prestate[addr].Storage[key]; ok { + return + } + t.prestate[addr].Storage[key] = t.env.StateDB.GetState(addr, key) +} diff --git a/x/evm/tracers/native/revertreason.go b/x/evm/tracers/native/revertreason.go new file mode 100644 index 00000000..d09b8610 --- /dev/null +++ b/x/evm/tracers/native/revertreason.go @@ -0,0 +1,108 @@ +// Copyright 2022 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package native + +import ( + "bytes" + "encoding/json" + "math/big" + "sync/atomic" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth/tracers" +) + +func init() { + register("revertReasonTracer", newRevertReasonTracer) +} + +var revertSelector = crypto.Keccak256([]byte("Error(string)"))[:4] + +// revertReasonTracer is a go implementation of the Tracer interface which +// track the error message or revert reason return by the contract. +type revertReasonTracer struct { + env *vm.EVM + revertReason string // The revert reason return from the tx, if tx success, empty string return + interrupt uint32 // Atomic flag to signal execution interruption + reason error // Textual reason for the interruption +} + +// newRevertReasonTracer returns a new revert reason tracer. +func newRevertReasonTracer(_ *tracers.Context, _ json.RawMessage) (tracers.Tracer, error) { + return &revertReasonTracer{}, nil +} + +// CaptureStart implements the EVMLogger interface to initialize the tracing operation. +func (t *revertReasonTracer) CaptureStart(env *vm.EVM, _ common.Address, _ common.Address, _ bool, _ []byte, _ uint64, _ *big.Int) { + t.env = env +} + +// CaptureEnd is called after the call finishes to finalize the tracing. +func (t *revertReasonTracer) CaptureEnd(output []byte, _ uint64, _ time.Duration, err error) { + if err != nil { + if err == vm.ErrExecutionReverted && len(output) > 4 && bytes.Equal(output[:4], revertSelector) { + errMsg, _ := abi.UnpackRevert(output) + t.revertReason = err.Error() + ": " + errMsg + } else { + t.revertReason = err.Error() + } + } +} + +// CaptureState implements the EVMLogger interface to trace a single step of VM execution. +func (t *revertReasonTracer) CaptureState(_ uint64, _ vm.OpCode, _, _ uint64, _ *vm.ScopeContext, _ []byte, _ int, _ error) { +} + +// CaptureFault implements the EVMLogger interface to trace an execution fault. +func (t *revertReasonTracer) CaptureFault(_ uint64, _ vm.OpCode, _, _ uint64, _ *vm.ScopeContext, _ int, _ error) { +} + +// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *revertReasonTracer) CaptureEnter(_ vm.OpCode, _ common.Address, _ common.Address, _ []byte, _ uint64, _ *big.Int) { + // Skip if tracing was interrupted + if atomic.LoadUint32(&t.interrupt) > 0 { + t.env.Cancel() + return + } +} + +// CaptureExit is called when EVM exits a scope, even if the scope didn't +// execute any code. +func (t *revertReasonTracer) CaptureExit(_ []byte, _ uint64, _ error) {} + +func (t *revertReasonTracer) CaptureTxStart(_ uint64) {} + +func (t *revertReasonTracer) CaptureTxEnd(_ uint64) {} + +// GetResult returns an error message json object. +func (t *revertReasonTracer) GetResult() (json.RawMessage, error) { + res, err := json.Marshal(t.revertReason) + if err != nil { + return nil, err + } + return res, t.reason +} + +// Stop terminates execution of the tracer at the first opportune moment. +func (t *revertReasonTracer) Stop(err error) { + t.reason = err + atomic.StoreUint32(&t.interrupt, 1) +} diff --git a/x/evm/tracers/native/tracer.go b/x/evm/tracers/native/tracer.go new file mode 100644 index 00000000..fda3e659 --- /dev/null +++ b/x/evm/tracers/native/tracer.go @@ -0,0 +1,83 @@ +// Copyright 2021 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +/* +Package native is a collection of tracers written in go. + +In order to add a native tracer and have it compiled into the binary, a new +file needs to be added to this folder, containing an implementation of the +`eth.tracers.Tracer` interface. + +Aside from implementing the tracer, it also needs to register itself, using the +`register` method -- and this needs to be done in the package initialization. + +Example: + +```golang +func init() { + register("noopTracerNative", newNoopTracer) +} +``` +*/ +package native + +import ( + "encoding/json" + "errors" + + "github.com/ethereum/go-ethereum/eth/tracers" +) + +// InitTracer retrieves the Go transaction tracers included in go-ethereum. +func InitTracer() { + tracers.RegisterLookup(false, lookup) +} + +// ctorFn is the constructor signature of a native tracer. +type ctorFn = func(*tracers.Context, json.RawMessage) (tracers.Tracer, error) + +/* +ctors is a map of package-local tracer constructors. + +We cannot be certain about the order of init-functions within a package, +The go spec (https://golang.org/ref/spec#Package_initialization) says + +> To ensure reproducible initialization behavior, build systems +> are encouraged to present multiple files belonging to the same +> package in lexical file name order to a compiler. + +Hence, we cannot make the map in init, but must make it upon first use. +*/ +var ctors map[string]ctorFn + +// register is used by native tracers to register their presence. +func register(name string, ctor ctorFn) { + if ctors == nil { + ctors = make(map[string]ctorFn) + } + ctors[name] = ctor +} + +// lookup returns a tracer, if one can be matched to the given name. +func lookup(name string, ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) { + if ctors == nil { + ctors = make(map[string]ctorFn) + } + if ctor, ok := ctors[name]; ok { + return ctor(ctx, cfg) + } + return nil, errors.New("no tracer found") +} From 7681d401340547a0c0a97f7fcdf2f6e5ec97d689 Mon Sep 17 00:00:00 2001 From: alexstratos Date: Mon, 13 Feb 2023 16:01:30 -0500 Subject: [PATCH 16/17] bump version to v0.9.1 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 797d8e9d..29cce82c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ BUILDDIR ?= $(CURDIR)/build -APP_VER := v0.9.0 +APP_VER := v0.9.1 COMMIT := $(GIT_COMMIT_HASH) TEST_DOCKER_REPO=stratos-chain-e2e From 62854552c6cac9ac0835938d3b09b07657d6cd1a Mon Sep 17 00:00:00 2001 From: WangLiStratos <104775735+WangLiStratos@users.noreply.github.com> Date: Mon, 13 Feb 2023 16:16:10 -0500 Subject: [PATCH 17/17] attribute current stake is not added now (#220) --- x/register/keeper/msg_server.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x/register/keeper/msg_server.go b/x/register/keeper/msg_server.go index ce281a77..8f7b1a06 100644 --- a/x/register/keeper/msg_server.go +++ b/x/register/keeper/msg_server.go @@ -321,7 +321,7 @@ func (k msgServer) HandleMsgUpdateResourceNodeStake(goCtx context.Context, msg * return &types.MsgUpdateResourceNodeStakeResponse{}, errors.New("invalid stake delta") } - ozoneLimitChange, completionTime, node, err := k.UpdateResourceNodeStake(ctx, networkAddr, ownerAddress, *msg.StakeDelta, msg.IncrStake) + ozoneLimitChange, completionTime, _, err := k.UpdateResourceNodeStake(ctx, networkAddr, ownerAddress, *msg.StakeDelta, msg.IncrStake) if err != nil { return nil, sdkerrors.Wrap(types.ErrUpdateResourceNodeStake, err.Error()) } @@ -333,7 +333,6 @@ func (k msgServer) HandleMsgUpdateResourceNodeStake(goCtx context.Context, msg * sdk.NewAttribute(types.AttributeKeyNetworkAddress, msg.NetworkAddress), sdk.NewAttribute(types.AttributeKeyIncrStakeBool, strconv.FormatBool(msg.IncrStake)), sdk.NewAttribute(types.AttributeKeyStakeDelta, msg.StakeDelta.String()), - sdk.NewAttribute(types.AttributeKeyCurrentStake, sdk.NewCoin(k.BondDenom(ctx), node.Tokens).String()), sdk.NewAttribute(types.AttributeKeyOZoneLimitChanges, ozoneLimitChange.String()), sdk.NewAttribute(types.AttributeKeyUnbondingMatureTime, completionTime.Format(time.RFC3339)), ),