Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
21f42d27c7 | ||
|
a031f9abca | ||
|
47bafe4619 | ||
|
fc0ade482d | ||
|
dbaaef07c7 | ||
|
b9e7398220 | ||
|
1aa98edb04 | ||
|
9794007231 | ||
|
d41612b891 | ||
|
3ef957206c | ||
|
151747bc81 | ||
|
5a6e2ec46f | ||
|
34cc262218 | ||
|
db925906f3 | ||
|
95dde36e1c | ||
|
9301487351 | ||
|
505ad2ab70 | ||
|
d28ef888ff | ||
|
feb9790325 |
28
Makefile
28
Makefile
@ -14,6 +14,7 @@ SIMAPP = ./app
|
|||||||
HTTPS_GIT := https://github.com/tharsis/ethermint.git
|
HTTPS_GIT := https://github.com/tharsis/ethermint.git
|
||||||
DOCKER := $(shell which docker)
|
DOCKER := $(shell which docker)
|
||||||
DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace bufbuild/buf
|
DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace bufbuild/buf
|
||||||
|
PROJECT_NAME = $(shell git remote get-url origin | xargs basename -s .git)
|
||||||
|
|
||||||
export GO111MODULE = on
|
export GO111MODULE = on
|
||||||
|
|
||||||
@ -422,25 +423,35 @@ format-fix:
|
|||||||
### Protobuf ###
|
### Protobuf ###
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
containerProtoVer=v0.2
|
protoVer=v0.2
|
||||||
containerProtoImage=tendermintdev/sdk-proto-gen:$(containerProtoVer)
|
protoImageName=tendermintdev/sdk-proto-gen:$(protoVer)
|
||||||
containerProtoGen=cosmos-sdk-proto-gen-$(containerProtoVer)
|
containerProtoGen=$(PROJECT_NAME)-proto-gen-$(protoVer)
|
||||||
containerProtoGenSwagger=cosmos-sdk-proto-gen-swagger-$(containerProtoVer)
|
containerProtoGenAny=$(PROJECT_NAME)-proto-gen-any-$(protoVer)
|
||||||
containerProtoFmt=cosmos-sdk-proto-fmt-$(containerProtoVer)
|
containerProtoGenSwagger=$(PROJECT_NAME)-proto-gen-swagger-$(protoVer)
|
||||||
|
containerProtoFmt=$(PROJECT_NAME)-proto-fmt-$(protoVer)
|
||||||
|
|
||||||
proto-all: proto-format proto-lint proto-gen
|
proto-all: proto-format proto-lint proto-gen
|
||||||
|
|
||||||
proto-gen:
|
proto-gen:
|
||||||
@echo "Generating Protobuf files"
|
@echo "Generating Protobuf files"
|
||||||
$(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace tendermintdev/sdk-proto-gen sh ./scripts/protocgen.sh
|
@if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoGen}$$"; then docker start -a $(containerProtoGen); else docker run --name $(containerProtoGen) -v $(CURDIR):/workspace --workdir /workspace $(protoImageName) \
|
||||||
|
sh ./scripts/protocgen.sh; fi
|
||||||
|
|
||||||
|
# This generates the SDK's custom wrapper for google.protobuf.Any. It should only be run manually when needed
|
||||||
|
proto-gen-any:
|
||||||
|
@echo "Generating Protobuf Any"
|
||||||
|
@if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoGenAny}$$"; then docker start -a $(containerProtoGenAny); else docker run --name $(containerProtoGenAny) -v $(CURDIR):/workspace --workdir /workspace $(protoImageName) \
|
||||||
|
sh ./scripts/protocgen-any.sh; fi
|
||||||
|
|
||||||
proto-swagger-gen:
|
proto-swagger-gen:
|
||||||
@echo "Generating Protobuf Swagger"
|
@echo "Generating Protobuf Swagger"
|
||||||
@./scripts/protoc-swagger-gen.sh
|
@if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoGenSwagger}$$"; then docker start -a $(containerProtoGenSwagger); else docker run --name $(containerProtoGenSwagger) -v $(CURDIR):/workspace --workdir /workspace $(protoImageName) \
|
||||||
|
sh ./scripts/protoc-swagger-gen.sh; fi
|
||||||
|
|
||||||
proto-format:
|
proto-format:
|
||||||
@echo "Formatting Protobuf files"
|
@echo "Formatting Protobuf files"
|
||||||
find ./ -not -path "./third_party/*" -name *.proto -exec clang-format -i {} \;
|
@if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoFmt}$$"; then docker start -a $(containerProtoFmt); else docker run --name $(containerProtoFmt) -v $(CURDIR):/workspace --workdir /workspace tendermintdev/docker-build-proto \
|
||||||
|
find ./ -not -path "./third_party/*" -name "*.proto" -exec clang-format -i {} \; ; fi
|
||||||
|
|
||||||
proto-lint:
|
proto-lint:
|
||||||
@$(DOCKER_BUF) lint --error-format=json
|
@$(DOCKER_BUF) lint --error-format=json
|
||||||
@ -576,3 +587,4 @@ release:
|
|||||||
release --rm-dist --skip-validate
|
release --rm-dist --skip-validate
|
||||||
|
|
||||||
.PHONY: release-dry-run release
|
.PHONY: release-dry-run release
|
||||||
|
|
||||||
|
@ -11,9 +11,9 @@ import (
|
|||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
|
||||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
authante "github.com/tharsis/ethermint/x/auth/ante"
|
||||||
|
|
||||||
channelkeeper "github.com/cosmos/ibc-go/modules/core/04-channel/keeper"
|
channelkeeper "github.com/cosmos/ibc-go/modules/core/04-channel/keeper"
|
||||||
ibcante "github.com/cosmos/ibc-go/modules/core/ante"
|
ibcante "github.com/cosmos/ibc-go/modules/core/ante"
|
||||||
|
@ -4,9 +4,10 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
authante "github.com/tharsis/ethermint/x/auth/ante"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
|
||||||
"github.com/palantir/stacktrace"
|
"github.com/palantir/stacktrace"
|
||||||
|
|
||||||
ethermint "github.com/tharsis/ethermint/types"
|
ethermint "github.com/tharsis/ethermint/types"
|
||||||
@ -28,7 +29,7 @@ type EVMKeeper interface {
|
|||||||
GetParams(ctx sdk.Context) evmtypes.Params
|
GetParams(ctx sdk.Context) evmtypes.Params
|
||||||
WithContext(ctx sdk.Context)
|
WithContext(ctx sdk.Context)
|
||||||
ResetRefundTransient(ctx sdk.Context)
|
ResetRefundTransient(ctx sdk.Context)
|
||||||
NewEVM(msg core.Message, config *params.ChainConfig, params evmtypes.Params, coinbase common.Address, tracer vm.Tracer) *vm.EVM
|
NewEVM(msg core.Message, config *params.ChainConfig, params evmtypes.Params, coinbase common.Address, tracer vm.EVMLogger) *vm.EVM
|
||||||
GetCodeHash(addr common.Address) common.Hash
|
GetCodeHash(addr common.Address) common.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
257
app/app.go
257
app/app.go
@ -2,6 +2,16 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/server"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/db"
|
||||||
|
types2 "github.com/cosmos/cosmos-sdk/store/types"
|
||||||
|
types3 "github.com/cosmos/cosmos-sdk/store/v2"
|
||||||
|
"github.com/cosmos/cosmos-sdk/store/v2/multi"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/middleware"
|
||||||
|
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@ -13,13 +23,10 @@ import (
|
|||||||
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
tmos "github.com/tendermint/tendermint/libs/os"
|
|
||||||
dbm "github.com/tendermint/tm-db"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
|
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
|
||||||
"github.com/cosmos/cosmos-sdk/client/rpc"
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
"github.com/cosmos/cosmos-sdk/server/api"
|
"github.com/cosmos/cosmos-sdk/server/api"
|
||||||
@ -63,6 +70,8 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||||
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
|
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
|
||||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||||
|
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||||
|
govv1beta2 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta2"
|
||||||
"github.com/cosmos/cosmos-sdk/x/mint"
|
"github.com/cosmos/cosmos-sdk/x/mint"
|
||||||
mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
|
mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
|
||||||
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
||||||
@ -86,7 +95,6 @@ import (
|
|||||||
ibctransferkeeper "github.com/cosmos/ibc-go/modules/apps/transfer/keeper"
|
ibctransferkeeper "github.com/cosmos/ibc-go/modules/apps/transfer/keeper"
|
||||||
ibctransfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types"
|
ibctransfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types"
|
||||||
ibc "github.com/cosmos/ibc-go/modules/core"
|
ibc "github.com/cosmos/ibc-go/modules/core"
|
||||||
ibcclient "github.com/cosmos/ibc-go/modules/core/02-client"
|
|
||||||
ibcclientclient "github.com/cosmos/ibc-go/modules/core/02-client/client"
|
ibcclientclient "github.com/cosmos/ibc-go/modules/core/02-client/client"
|
||||||
porttypes "github.com/cosmos/ibc-go/modules/core/05-port/types"
|
porttypes "github.com/cosmos/ibc-go/modules/core/05-port/types"
|
||||||
ibchost "github.com/cosmos/ibc-go/modules/core/24-host"
|
ibchost "github.com/cosmos/ibc-go/modules/core/24-host"
|
||||||
@ -95,9 +103,16 @@ import (
|
|||||||
// unnamed import of statik for swagger UI support
|
// unnamed import of statik for swagger UI support
|
||||||
_ "github.com/tharsis/ethermint/client/docs/statik"
|
_ "github.com/tharsis/ethermint/client/docs/statik"
|
||||||
|
|
||||||
"github.com/tharsis/ethermint/app/ante"
|
|
||||||
srvflags "github.com/tharsis/ethermint/server/flags"
|
srvflags "github.com/tharsis/ethermint/server/flags"
|
||||||
ethermint "github.com/tharsis/ethermint/types"
|
ethermint "github.com/tharsis/ethermint/types"
|
||||||
|
|
||||||
|
"github.com/tharsis/ethermint/x/auction"
|
||||||
|
auctionkeeper "github.com/tharsis/ethermint/x/auction/keeper"
|
||||||
|
auctiontypes "github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
"github.com/tharsis/ethermint/x/bond"
|
||||||
|
bondkeeper "github.com/tharsis/ethermint/x/bond/keeper"
|
||||||
|
bondtypes "github.com/tharsis/ethermint/x/bond/types"
|
||||||
|
|
||||||
"github.com/tharsis/ethermint/x/evm"
|
"github.com/tharsis/ethermint/x/evm"
|
||||||
evmrest "github.com/tharsis/ethermint/x/evm/client/rest"
|
evmrest "github.com/tharsis/ethermint/x/evm/client/rest"
|
||||||
evmkeeper "github.com/tharsis/ethermint/x/evm/keeper"
|
evmkeeper "github.com/tharsis/ethermint/x/evm/keeper"
|
||||||
@ -105,6 +120,10 @@ import (
|
|||||||
"github.com/tharsis/ethermint/x/feemarket"
|
"github.com/tharsis/ethermint/x/feemarket"
|
||||||
feemarketkeeper "github.com/tharsis/ethermint/x/feemarket/keeper"
|
feemarketkeeper "github.com/tharsis/ethermint/x/feemarket/keeper"
|
||||||
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
|
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
|
||||||
|
|
||||||
|
"github.com/tharsis/ethermint/x/nameservice"
|
||||||
|
nameservicekeeper "github.com/tharsis/ethermint/x/nameservice/keeper"
|
||||||
|
nameservicetypes "github.com/tharsis/ethermint/x/nameservice/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -150,6 +169,10 @@ var (
|
|||||||
// Ethermint modules
|
// Ethermint modules
|
||||||
evm.AppModuleBasic{},
|
evm.AppModuleBasic{},
|
||||||
feemarket.AppModuleBasic{},
|
feemarket.AppModuleBasic{},
|
||||||
|
// Vulcanize DXNS modules
|
||||||
|
auction.AppModuleBasic{},
|
||||||
|
bond.AppModuleBasic{},
|
||||||
|
nameservice.AppModuleBasic{},
|
||||||
)
|
)
|
||||||
|
|
||||||
// module account permissions
|
// module account permissions
|
||||||
@ -162,6 +185,13 @@ var (
|
|||||||
govtypes.ModuleName: {authtypes.Burner},
|
govtypes.ModuleName: {authtypes.Burner},
|
||||||
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
|
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
|
||||||
evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, // used for secure addition and subtraction of balance using module account
|
evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, // used for secure addition and subtraction of balance using module account
|
||||||
|
|
||||||
|
auctiontypes.ModuleName: nil,
|
||||||
|
auctiontypes.AuctionBurnModuleAccountName: nil,
|
||||||
|
nameservicetypes.ModuleName: nil,
|
||||||
|
nameservicetypes.RecordRentModuleAccountName: nil,
|
||||||
|
nameservicetypes.AuthorityRentModuleAccountName: nil,
|
||||||
|
bondtypes.ModuleName: nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
// module accounts that are allowed to receive tokens
|
// module accounts that are allowed to receive tokens
|
||||||
@ -184,13 +214,15 @@ type EthermintApp struct {
|
|||||||
cdc *codec.LegacyAmino
|
cdc *codec.LegacyAmino
|
||||||
appCodec codec.Codec
|
appCodec codec.Codec
|
||||||
interfaceRegistry types.InterfaceRegistry
|
interfaceRegistry types.InterfaceRegistry
|
||||||
|
legacyRouter *middleware.LegacyRouter
|
||||||
|
msgSvcRouter *middleware.MsgServiceRouter
|
||||||
|
|
||||||
invCheckPeriod uint
|
invCheckPeriod uint
|
||||||
|
|
||||||
// keys to access the substores
|
// keys to access the substores
|
||||||
keys map[string]*sdk.KVStoreKey
|
keys map[string]*types2.KVStoreKey
|
||||||
tkeys map[string]*sdk.TransientStoreKey
|
tkeys map[string]*types2.TransientStoreKey
|
||||||
memKeys map[string]*sdk.MemoryStoreKey
|
memKeys map[string]*types2.MemoryStoreKey
|
||||||
|
|
||||||
// keepers
|
// keepers
|
||||||
AccountKeeper authkeeper.AccountKeeper
|
AccountKeeper authkeeper.AccountKeeper
|
||||||
@ -218,6 +250,12 @@ type EthermintApp struct {
|
|||||||
EvmKeeper *evmkeeper.Keeper
|
EvmKeeper *evmkeeper.Keeper
|
||||||
FeeMarketKeeper feemarketkeeper.Keeper
|
FeeMarketKeeper feemarketkeeper.Keeper
|
||||||
|
|
||||||
|
// DXNS keepers
|
||||||
|
AuctionKeeper auctionkeeper.Keeper
|
||||||
|
BondKeeper bondkeeper.Keeper
|
||||||
|
NameServiceKeeper nameservicekeeper.Keeper
|
||||||
|
NameServiceRecordKeeper nameservicekeeper.RecordKeeper
|
||||||
|
|
||||||
// the module manager
|
// the module manager
|
||||||
mm *module.Manager
|
mm *module.Manager
|
||||||
|
|
||||||
@ -231,32 +269,19 @@ type EthermintApp struct {
|
|||||||
// NewEthermintApp returns a reference to a new initialized Ethermint application.
|
// NewEthermintApp returns a reference to a new initialized Ethermint application.
|
||||||
func NewEthermintApp(
|
func NewEthermintApp(
|
||||||
logger log.Logger,
|
logger log.Logger,
|
||||||
db dbm.DB,
|
db db.DBConnection,
|
||||||
traceStore io.Writer,
|
traceStore io.Writer,
|
||||||
loadLatest bool,
|
|
||||||
skipUpgradeHeights map[int64]bool,
|
skipUpgradeHeights map[int64]bool,
|
||||||
homePath string,
|
homePath string,
|
||||||
invCheckPeriod uint,
|
invCheckPeriod uint,
|
||||||
encodingConfig simappparams.EncodingConfig,
|
encodingConfig simappparams.EncodingConfig,
|
||||||
appOpts servertypes.AppOptions,
|
appOpts servertypes.AppOptions,
|
||||||
baseAppOptions ...func(*baseapp.BaseApp),
|
baseAppOptions ...baseapp.AppOption,
|
||||||
) *EthermintApp {
|
) *EthermintApp {
|
||||||
appCodec := encodingConfig.Marshaler
|
appCodec := encodingConfig.Codec
|
||||||
cdc := encodingConfig.Amino
|
cdc := encodingConfig.Amino
|
||||||
interfaceRegistry := encodingConfig.InterfaceRegistry
|
interfaceRegistry := encodingConfig.InterfaceRegistry
|
||||||
|
|
||||||
// NOTE we use custom transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx
|
|
||||||
bApp := baseapp.NewBaseApp(
|
|
||||||
appName,
|
|
||||||
logger,
|
|
||||||
db,
|
|
||||||
encodingConfig.TxConfig.TxDecoder(),
|
|
||||||
baseAppOptions...,
|
|
||||||
)
|
|
||||||
bApp.SetCommitMultiStoreTracer(traceStore)
|
|
||||||
bApp.SetVersion(version.Version)
|
|
||||||
bApp.SetInterfaceRegistry(interfaceRegistry)
|
|
||||||
|
|
||||||
keys := sdk.NewKVStoreKeys(
|
keys := sdk.NewKVStoreKeys(
|
||||||
// SDK keys
|
// SDK keys
|
||||||
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
|
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
|
||||||
@ -268,17 +293,67 @@ func NewEthermintApp(
|
|||||||
ibchost.StoreKey, ibctransfertypes.StoreKey,
|
ibchost.StoreKey, ibctransfertypes.StoreKey,
|
||||||
// ethermint keys
|
// ethermint keys
|
||||||
evmtypes.StoreKey, feemarkettypes.StoreKey,
|
evmtypes.StoreKey, feemarkettypes.StoreKey,
|
||||||
|
// dxns keys
|
||||||
|
auctiontypes.StoreKey,
|
||||||
|
bondtypes.StoreKey,
|
||||||
|
nameservicetypes.StoreKey,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add the EVM transient store key
|
// Add the EVM transient store key
|
||||||
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey)
|
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey)
|
||||||
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
|
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
|
||||||
|
|
||||||
|
// initialize stores
|
||||||
|
setNamespaces := func(config *multi.StoreParams, ver uint64) error {
|
||||||
|
for _, key := range keys {
|
||||||
|
typ, err := types3.StoreKeyToType(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = config.RegisterSubstore(key, typ); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, key := range memKeys {
|
||||||
|
typ, err := types3.StoreKeyToType(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = config.RegisterSubstore(key, typ); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, key := range tkeys {
|
||||||
|
typ, err := types3.StoreKeyToType(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = config.RegisterSubstore(key, typ); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
baseAppOptions = append(baseAppOptions, baseapp.StoreOption(setNamespaces))
|
||||||
|
|
||||||
|
// NOTE we use custom transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx
|
||||||
|
bApp := baseapp.NewBaseApp(
|
||||||
|
appName,
|
||||||
|
logger,
|
||||||
|
db,
|
||||||
|
baseAppOptions...,
|
||||||
|
)
|
||||||
|
bApp.SetCommitMultiStoreTracer(traceStore)
|
||||||
|
bApp.SetVersion(version.Version)
|
||||||
|
bApp.SetInterfaceRegistry(interfaceRegistry)
|
||||||
|
|
||||||
app := &EthermintApp{
|
app := &EthermintApp{
|
||||||
BaseApp: bApp,
|
BaseApp: bApp,
|
||||||
cdc: cdc,
|
cdc: cdc,
|
||||||
appCodec: appCodec,
|
appCodec: appCodec,
|
||||||
interfaceRegistry: interfaceRegistry,
|
interfaceRegistry: interfaceRegistry,
|
||||||
|
legacyRouter: middleware.NewLegacyRouter(),
|
||||||
|
msgSvcRouter: middleware.NewMsgServiceRouter(interfaceRegistry),
|
||||||
invCheckPeriod: invCheckPeriod,
|
invCheckPeriod: invCheckPeriod,
|
||||||
keys: keys,
|
keys: keys,
|
||||||
tkeys: tkeys,
|
tkeys: tkeys,
|
||||||
@ -288,7 +363,7 @@ func NewEthermintApp(
|
|||||||
// init params keeper and subspaces
|
// init params keeper and subspaces
|
||||||
app.ParamsKeeper = initParamsKeeper(appCodec, cdc, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
|
app.ParamsKeeper = initParamsKeeper(appCodec, cdc, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
|
||||||
// set the BaseApp's parameter store
|
// set the BaseApp's parameter store
|
||||||
bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramskeeper.ConsensusParamsKeyTable()))
|
bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramstypes.ConsensusParamsKeyTable()))
|
||||||
|
|
||||||
// add capability keeper and ScopeToModule for ibc module
|
// add capability keeper and ScopeToModule for ibc module
|
||||||
app.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey])
|
app.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey])
|
||||||
@ -303,6 +378,7 @@ func NewEthermintApp(
|
|||||||
// use custom Ethermint account for contracts
|
// use custom Ethermint account for contracts
|
||||||
app.AccountKeeper = authkeeper.NewAccountKeeper(
|
app.AccountKeeper = authkeeper.NewAccountKeeper(
|
||||||
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), ethermint.ProtoAccount, maccPerms,
|
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), ethermint.ProtoAccount, maccPerms,
|
||||||
|
sdk.Bech32MainPrefix,
|
||||||
)
|
)
|
||||||
app.BankKeeper = bankkeeper.NewBaseKeeper(
|
app.BankKeeper = bankkeeper.NewBaseKeeper(
|
||||||
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs(),
|
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs(),
|
||||||
@ -316,7 +392,7 @@ func NewEthermintApp(
|
|||||||
)
|
)
|
||||||
app.DistrKeeper = distrkeeper.NewKeeper(
|
app.DistrKeeper = distrkeeper.NewKeeper(
|
||||||
appCodec, keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
|
appCodec, keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
|
||||||
&stakingKeeper, authtypes.FeeCollectorName, app.ModuleAccountAddrs(),
|
&stakingKeeper, authtypes.FeeCollectorName,
|
||||||
)
|
)
|
||||||
app.SlashingKeeper = slashingkeeper.NewKeeper(
|
app.SlashingKeeper = slashingkeeper.NewKeeper(
|
||||||
appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName),
|
appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName),
|
||||||
@ -333,7 +409,8 @@ func NewEthermintApp(
|
|||||||
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
|
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
|
||||||
)
|
)
|
||||||
|
|
||||||
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.BaseApp.MsgServiceRouter())
|
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec,
|
||||||
|
app.msgSvcRouter, app.AccountKeeper)
|
||||||
|
|
||||||
tracer := cast.ToString(appOpts.Get(srvflags.EVMTracer))
|
tracer := cast.ToString(appOpts.Get(srvflags.EVMTracer))
|
||||||
|
|
||||||
@ -348,22 +425,47 @@ func NewEthermintApp(
|
|||||||
appCodec, keys[feemarkettypes.StoreKey], app.GetSubspace(feemarkettypes.ModuleName),
|
appCodec, keys[feemarkettypes.StoreKey], app.GetSubspace(feemarkettypes.ModuleName),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Create Vulcanize dxns keepers
|
||||||
|
|
||||||
|
app.AuctionKeeper = auctionkeeper.NewKeeper(
|
||||||
|
app.AccountKeeper, app.BankKeeper, keys[auctiontypes.StoreKey],
|
||||||
|
appCodec, app.GetSubspace(auctiontypes.ModuleName),
|
||||||
|
)
|
||||||
|
|
||||||
|
app.NameServiceRecordKeeper = nameservicekeeper.NewRecordKeeper(app.AuctionKeeper, keys[nameservicetypes.StoreKey], appCodec)
|
||||||
|
|
||||||
|
app.AuctionKeeper.SetUsageKeepers([]auctiontypes.AuctionUsageKeeper{app.NameServiceRecordKeeper})
|
||||||
|
|
||||||
|
app.BondKeeper = bondkeeper.NewKeeper(
|
||||||
|
appCodec, app.AccountKeeper, app.BankKeeper,
|
||||||
|
[]bondtypes.BondUsageKeeper{app.NameServiceRecordKeeper}, keys[bondtypes.StoreKey], app.GetSubspace(bondtypes.ModuleName),
|
||||||
|
)
|
||||||
|
|
||||||
|
app.NameServiceKeeper = nameservicekeeper.NewKeeper(
|
||||||
|
appCodec, app.AccountKeeper, app.BankKeeper,
|
||||||
|
app.NameServiceRecordKeeper, app.BondKeeper, app.AuctionKeeper,
|
||||||
|
keys[nameservicetypes.StoreKey], app.GetSubspace(nameservicetypes.ModuleName),
|
||||||
|
)
|
||||||
|
|
||||||
// Create IBC Keeper
|
// Create IBC Keeper
|
||||||
app.IBCKeeper = ibckeeper.NewKeeper(
|
app.IBCKeeper = ibckeeper.NewKeeper(
|
||||||
appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper,
|
appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper,
|
||||||
)
|
)
|
||||||
|
|
||||||
// register the proposal types
|
// register the proposal types
|
||||||
govRouter := govtypes.NewRouter()
|
govRouter := govv1beta1.NewRouter()
|
||||||
govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler).
|
govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler).
|
||||||
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
|
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
|
||||||
AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)).
|
AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)).
|
||||||
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)).
|
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper))
|
||||||
AddRoute(ibchost.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper))
|
govConfig := govtypes.DefaultConfig()
|
||||||
|
/*
|
||||||
|
Example of setting gov params:
|
||||||
|
govConfig.MaxMetadataLen = 10000
|
||||||
|
*/
|
||||||
govKeeper := govkeeper.NewKeeper(
|
govKeeper := govkeeper.NewKeeper(
|
||||||
appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
|
appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
|
||||||
&stakingKeeper, govRouter,
|
&stakingKeeper, govRouter, app.msgSvcRouter, govConfig,
|
||||||
)
|
)
|
||||||
|
|
||||||
app.GovKeeper = *govKeeper.SetHooks(
|
app.GovKeeper = *govKeeper.SetHooks(
|
||||||
@ -412,7 +514,7 @@ func NewEthermintApp(
|
|||||||
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
|
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
|
||||||
crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants),
|
crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants),
|
||||||
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
|
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
|
||||||
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper),
|
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil),
|
||||||
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
||||||
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
||||||
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
|
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
|
||||||
@ -428,6 +530,10 @@ func NewEthermintApp(
|
|||||||
// Ethermint app modules
|
// Ethermint app modules
|
||||||
evm.NewAppModule(app.EvmKeeper, app.AccountKeeper),
|
evm.NewAppModule(app.EvmKeeper, app.AccountKeeper),
|
||||||
feemarket.NewAppModule(app.FeeMarketKeeper),
|
feemarket.NewAppModule(app.FeeMarketKeeper),
|
||||||
|
// DXNs modules
|
||||||
|
auction.NewAppModule(appCodec, app.AuctionKeeper),
|
||||||
|
bond.NewAppModule(appCodec, app.BondKeeper),
|
||||||
|
nameservice.NewAppModule(app.NameServiceKeeper),
|
||||||
)
|
)
|
||||||
|
|
||||||
// During begin block slashing happens after distr.BeginBlocker so that
|
// During begin block slashing happens after distr.BeginBlocker so that
|
||||||
@ -448,6 +554,8 @@ func NewEthermintApp(
|
|||||||
app.mm.SetOrderEndBlockers(
|
app.mm.SetOrderEndBlockers(
|
||||||
crisistypes.ModuleName, govtypes.ModuleName, stakingtypes.ModuleName,
|
crisistypes.ModuleName, govtypes.ModuleName, stakingtypes.ModuleName,
|
||||||
evmtypes.ModuleName, feemarkettypes.ModuleName,
|
evmtypes.ModuleName, feemarkettypes.ModuleName,
|
||||||
|
nameservicetypes.ModuleName,
|
||||||
|
auctiontypes.ModuleName,
|
||||||
)
|
)
|
||||||
|
|
||||||
// NOTE: The genutils module must occur after staking so that pools are
|
// NOTE: The genutils module must occur after staking so that pools are
|
||||||
@ -463,14 +571,18 @@ func NewEthermintApp(
|
|||||||
authz.ModuleName, feegrant.ModuleName,
|
authz.ModuleName, feegrant.ModuleName,
|
||||||
// Ethermint modules
|
// Ethermint modules
|
||||||
evmtypes.ModuleName, feemarkettypes.ModuleName,
|
evmtypes.ModuleName, feemarkettypes.ModuleName,
|
||||||
|
// DXNS modules
|
||||||
|
auctiontypes.ModuleName,
|
||||||
|
bondtypes.ModuleName,
|
||||||
|
nameservicetypes.ModuleName,
|
||||||
|
|
||||||
// NOTE: crisis module must go at the end to check for invariants on each module
|
// NOTE: crisis module must go at the end to check for invariants on each module
|
||||||
crisistypes.ModuleName,
|
crisistypes.ModuleName,
|
||||||
)
|
)
|
||||||
|
|
||||||
app.mm.RegisterInvariants(&app.CrisisKeeper)
|
app.mm.RegisterInvariants(&app.CrisisKeeper)
|
||||||
app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino)
|
app.mm.RegisterRoutes(app.legacyRouter, app.QueryRouter(), encodingConfig.Amino)
|
||||||
app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
|
app.configurator = module.NewConfigurator(app.appCodec, app.msgSvcRouter, app.GRPCQueryRouter())
|
||||||
app.mm.RegisterServices(app.configurator)
|
app.mm.RegisterServices(app.configurator)
|
||||||
|
|
||||||
// add test gRPC service for testing gRPC queries in isolation
|
// add test gRPC service for testing gRPC queries in isolation
|
||||||
@ -485,7 +597,7 @@ func NewEthermintApp(
|
|||||||
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
|
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
|
||||||
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
|
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
|
||||||
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
|
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
|
||||||
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper),
|
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil),
|
||||||
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
|
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
|
||||||
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
||||||
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
||||||
@ -499,37 +611,54 @@ func NewEthermintApp(
|
|||||||
|
|
||||||
app.sm.RegisterStoreDecoders()
|
app.sm.RegisterStoreDecoders()
|
||||||
|
|
||||||
// initialize stores
|
|
||||||
app.MountKVStores(keys)
|
|
||||||
app.MountTransientStores(tkeys)
|
|
||||||
app.MountMemoryStores(memKeys)
|
|
||||||
|
|
||||||
// initialize BaseApp
|
// initialize BaseApp
|
||||||
app.SetInitChainer(app.InitChainer)
|
app.SetInitChainer(app.InitChainer)
|
||||||
app.SetBeginBlocker(app.BeginBlocker)
|
app.SetBeginBlocker(app.BeginBlocker)
|
||||||
|
|
||||||
// use Ethermint's custom AnteHandler
|
// TODO: use Ethermint's custom AnteHandler
|
||||||
app.SetAnteHandler(
|
app.setTxHandler(encodingConfig.TxConfig, cast.ToStringSlice(appOpts.Get(server.FlagIndexEvents)))
|
||||||
ante.NewAnteHandler(
|
|
||||||
app.AccountKeeper, app.BankKeeper, app.EvmKeeper, app.FeeGrantKeeper, app.IBCKeeper.ChannelKeeper,
|
|
||||||
encodingConfig.TxConfig.SignModeHandler(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
app.SetEndBlocker(app.EndBlocker)
|
app.SetEndBlocker(app.EndBlocker)
|
||||||
|
|
||||||
if loadLatest {
|
|
||||||
if err := app.LoadLatestVersion(); err != nil {
|
|
||||||
tmos.Exit(err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
app.ScopedIBCKeeper = scopedIBCKeeper
|
app.ScopedIBCKeeper = scopedIBCKeeper
|
||||||
app.ScopedTransferKeeper = scopedTransferKeeper
|
app.ScopedTransferKeeper = scopedTransferKeeper
|
||||||
|
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (app *EthermintApp) setTxHandler(txConfig client.TxConfig, indexEventsStr []string) {
|
||||||
|
indexEvents := map[string]struct{}{}
|
||||||
|
for _, e := range indexEventsStr {
|
||||||
|
indexEvents[e] = struct{}{}
|
||||||
|
}
|
||||||
|
// need to sub in custom tx handler
|
||||||
|
/*
|
||||||
|
app.SetTxHandler(
|
||||||
|
ante.NewAnteHandler(
|
||||||
|
app.AccountKeeper, app.BankKeeper, app.EvmKeeper, app.FeeGrantKeeper, app.IBCKeeper.ChannelKeeper,
|
||||||
|
encodingConfig.TxConfig.SignModeHandler(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
*/
|
||||||
|
txHandler, err := middleware.NewDefaultTxHandler(middleware.TxHandlerOptions{
|
||||||
|
Debug: app.Trace(),
|
||||||
|
IndexEvents: indexEvents,
|
||||||
|
LegacyRouter: app.legacyRouter,
|
||||||
|
MsgServiceRouter: app.msgSvcRouter,
|
||||||
|
AccountKeeper: app.AccountKeeper,
|
||||||
|
BankKeeper: app.BankKeeper,
|
||||||
|
FeegrantKeeper: app.FeeGrantKeeper,
|
||||||
|
SignModeHandler: txConfig.SignModeHandler(),
|
||||||
|
SigGasConsumer: middleware.DefaultSigVerificationGasConsumer,
|
||||||
|
TxDecoder: txConfig.TxDecoder(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
app.SetTxHandler(txHandler)
|
||||||
|
}
|
||||||
|
|
||||||
// Name returns the name of the App
|
// Name returns the name of the App
|
||||||
func (app *EthermintApp) Name() string { return app.BaseApp.Name() }
|
func (app *EthermintApp) Name() string { return app.BaseApp.Name() }
|
||||||
|
|
||||||
@ -555,7 +684,7 @@ func (app *EthermintApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain)
|
|||||||
|
|
||||||
// LoadHeight loads state at a particular height
|
// LoadHeight loads state at a particular height
|
||||||
func (app *EthermintApp) LoadHeight(height int64) error {
|
func (app *EthermintApp) LoadHeight(height int64) error {
|
||||||
return app.LoadVersion(height)
|
return errors.New("cannot load arbitrary height")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModuleAccountAddrs returns all the app's module account addresses.
|
// ModuleAccountAddrs returns all the app's module account addresses.
|
||||||
@ -603,21 +732,21 @@ func (app *EthermintApp) InterfaceRegistry() types.InterfaceRegistry {
|
|||||||
// GetKey returns the KVStoreKey for the provided store key.
|
// GetKey returns the KVStoreKey for the provided store key.
|
||||||
//
|
//
|
||||||
// NOTE: This is solely to be used for testing purposes.
|
// NOTE: This is solely to be used for testing purposes.
|
||||||
func (app *EthermintApp) GetKey(storeKey string) *sdk.KVStoreKey {
|
func (app *EthermintApp) GetKey(storeKey string) *types3.KVStoreKey {
|
||||||
return app.keys[storeKey]
|
return app.keys[storeKey]
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTKey returns the TransientStoreKey for the provided store key.
|
// GetTKey returns the TransientStoreKey for the provided store key.
|
||||||
//
|
//
|
||||||
// NOTE: This is solely to be used for testing purposes.
|
// NOTE: This is solely to be used for testing purposes.
|
||||||
func (app *EthermintApp) GetTKey(storeKey string) *sdk.TransientStoreKey {
|
func (app *EthermintApp) GetTKey(storeKey string) *types3.TransientStoreKey {
|
||||||
return app.tkeys[storeKey]
|
return app.tkeys[storeKey]
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMemKey returns the MemStoreKey for the provided mem key.
|
// GetMemKey returns the MemStoreKey for the provided mem key.
|
||||||
//
|
//
|
||||||
// NOTE: This is solely used for testing purposes.
|
// NOTE: This is solely used for testing purposes.
|
||||||
func (app *EthermintApp) GetMemKey(storeKey string) *sdk.MemoryStoreKey {
|
func (app *EthermintApp) GetMemKey(storeKey string) *types3.MemoryStoreKey {
|
||||||
return app.memKeys[storeKey]
|
return app.memKeys[storeKey]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -638,7 +767,6 @@ func (app *EthermintApp) SimulationManager() *module.SimulationManager {
|
|||||||
// API server.
|
// API server.
|
||||||
func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
|
func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
|
||||||
clientCtx := apiSvr.ClientCtx
|
clientCtx := apiSvr.ClientCtx
|
||||||
rpc.RegisterRoutes(clientCtx, apiSvr.Router)
|
|
||||||
|
|
||||||
evmrest.RegisterTxRoutes(clientCtx, apiSvr.Router)
|
evmrest.RegisterTxRoutes(clientCtx, apiSvr.Router)
|
||||||
|
|
||||||
@ -688,7 +816,7 @@ func GetMaccPerms() map[string][]string {
|
|||||||
|
|
||||||
// initParamsKeeper init params keeper and its subspaces
|
// initParamsKeeper init params keeper and its subspaces
|
||||||
func initParamsKeeper(
|
func initParamsKeeper(
|
||||||
appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey sdk.StoreKey) paramskeeper.Keeper {
|
appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey types3.StoreKey) paramskeeper.Keeper {
|
||||||
paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey)
|
paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey)
|
||||||
|
|
||||||
// SDK subspaces
|
// SDK subspaces
|
||||||
@ -698,12 +826,17 @@ func initParamsKeeper(
|
|||||||
paramsKeeper.Subspace(minttypes.ModuleName)
|
paramsKeeper.Subspace(minttypes.ModuleName)
|
||||||
paramsKeeper.Subspace(distrtypes.ModuleName)
|
paramsKeeper.Subspace(distrtypes.ModuleName)
|
||||||
paramsKeeper.Subspace(slashingtypes.ModuleName)
|
paramsKeeper.Subspace(slashingtypes.ModuleName)
|
||||||
paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govtypes.ParamKeyTable())
|
paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govv1beta2.ParamKeyTable())
|
||||||
paramsKeeper.Subspace(crisistypes.ModuleName)
|
paramsKeeper.Subspace(crisistypes.ModuleName)
|
||||||
paramsKeeper.Subspace(ibctransfertypes.ModuleName)
|
paramsKeeper.Subspace(ibctransfertypes.ModuleName)
|
||||||
paramsKeeper.Subspace(ibchost.ModuleName)
|
paramsKeeper.Subspace(ibchost.ModuleName)
|
||||||
// ethermint subspaces
|
// ethermint subspaces
|
||||||
paramsKeeper.Subspace(evmtypes.ModuleName)
|
paramsKeeper.Subspace(evmtypes.ModuleName)
|
||||||
paramsKeeper.Subspace(feemarkettypes.ModuleName)
|
paramsKeeper.Subspace(feemarkettypes.ModuleName)
|
||||||
|
// dxns subspaces
|
||||||
|
paramsKeeper.Subspace(auctiontypes.ModuleName)
|
||||||
|
paramsKeeper.Subspace(bondtypes.ModuleName)
|
||||||
|
paramsKeeper.Subspace(nameservicetypes.ModuleName)
|
||||||
|
|
||||||
return paramsKeeper
|
return paramsKeeper
|
||||||
}
|
}
|
||||||
|
@ -2,23 +2,27 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/db/memdb"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
dbm "github.com/tendermint/tm-db"
|
|
||||||
|
|
||||||
"github.com/tharsis/ethermint/encoding"
|
"github.com/tharsis/ethermint/encoding"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEthermintAppExport(t *testing.T) {
|
func TestEthermintAppExport(t *testing.T) {
|
||||||
db := dbm.NewMemDB()
|
db := memdb.NewDB()
|
||||||
app := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
logger, err := log.NewDefaultLogger("plain", "info", false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
||||||
|
|
||||||
genesisState := NewDefaultGenesisState()
|
genesisState := NewDefaultGenesisState()
|
||||||
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
|
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
|
||||||
@ -35,7 +39,11 @@ func TestEthermintAppExport(t *testing.T) {
|
|||||||
app.Commit()
|
app.Commit()
|
||||||
|
|
||||||
// Making a new app object with the db, so that initchain hasn't been called
|
// Making a new app object with the db, so that initchain hasn't been called
|
||||||
app2 := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
logger, err = log.NewDefaultLogger("plain", "info", false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
app2 := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
||||||
_, err = app2.ExportAppStateAndValidators(false, []string{})
|
_, err = app2.ExportAppStateAndValidators(false, []string{})
|
||||||
require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
|
require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
|
||||||
}
|
}
|
||||||
|
@ -2,19 +2,18 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/db/memdb"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
dbm "github.com/tendermint/tm-db"
|
|
||||||
"github.com/tharsis/ethermint/encoding"
|
"github.com/tharsis/ethermint/encoding"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkEthermintApp_ExportAppStateAndValidators(b *testing.B) {
|
func BenchmarkEthermintApp_ExportAppStateAndValidators(b *testing.B) {
|
||||||
db := dbm.NewMemDB()
|
db := memdb.NewDB()
|
||||||
app := NewEthermintApp(log.NewTMLogger(io.Discard), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
app := NewEthermintApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
||||||
|
|
||||||
genesisState := NewDefaultGenesisState()
|
genesisState := NewDefaultGenesisState()
|
||||||
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
|
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
|
||||||
@ -36,7 +35,7 @@ func BenchmarkEthermintApp_ExportAppStateAndValidators(b *testing.B) {
|
|||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
// Making a new app object with the db, so that initchain hasn't been called
|
// Making a new app object with the db, so that initchain hasn't been called
|
||||||
app2 := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(io.Discard)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
app2 := NewEthermintApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
||||||
if _, err := app2.ExportAppStateAndValidators(false, []string{}); err != nil {
|
if _, err := app2.ExportAppStateAndValidators(false, []string{}); err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ import (
|
|||||||
// NewDefaultGenesisState generates the default state for the application.
|
// NewDefaultGenesisState generates the default state for the application.
|
||||||
func NewDefaultGenesisState() simapp.GenesisState {
|
func NewDefaultGenesisState() simapp.GenesisState {
|
||||||
encCfg := encoding.MakeConfig(ModuleBasics)
|
encCfg := encoding.MakeConfig(ModuleBasics)
|
||||||
return ModuleBasics.DefaultGenesis(encCfg.Marshaler)
|
return ModuleBasics.DefaultGenesis(encCfg.Codec)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExportAppStateAndValidators exports the state of the application for a genesis
|
// ExportAppStateAndValidators exports the state of the application for a genesis
|
||||||
|
@ -4,6 +4,10 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/db/memdb"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
"github.com/tharsis/ethermint/encoding"
|
"github.com/tharsis/ethermint/encoding"
|
||||||
|
|
||||||
@ -11,13 +15,12 @@ import (
|
|||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
dbm "github.com/tendermint/tm-db"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultConsensusParams defines the default Tendermint consensus params used in
|
// DefaultConsensusParams defines the default Tendermint consensus params used in
|
||||||
// EthermintApp testing.
|
// EthermintApp testing.
|
||||||
var DefaultConsensusParams = &abci.ConsensusParams{
|
var DefaultConsensusParams = &tmproto.ConsensusParams{
|
||||||
Block: &abci.BlockParams{
|
Block: &tmproto.BlockParams{
|
||||||
MaxBytes: 200000,
|
MaxBytes: 200000,
|
||||||
MaxGas: -1, // no limit
|
MaxGas: -1, // no limit
|
||||||
},
|
},
|
||||||
@ -35,7 +38,7 @@ var DefaultConsensusParams = &abci.ConsensusParams{
|
|||||||
|
|
||||||
// Setup initializes a new EthermintApp. A Nop logger is set in EthermintApp.
|
// Setup initializes a new EthermintApp. A Nop logger is set in EthermintApp.
|
||||||
func Setup(isCheckTx bool) *EthermintApp {
|
func Setup(isCheckTx bool) *EthermintApp {
|
||||||
db := dbm.NewMemDB()
|
db := memdb.NewDB()
|
||||||
app := NewEthermintApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 5, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
app := NewEthermintApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 5, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
||||||
if !isCheckTx {
|
if !isCheckTx {
|
||||||
// init chain must be called to stop deliverState from being nil
|
// init chain must be called to stop deliverState from being nil
|
||||||
@ -58,3 +61,15 @@ func Setup(isCheckTx bool) *EthermintApp {
|
|||||||
|
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateRandomAccounts will generate random accounts
|
||||||
|
func CreateRandomAccounts(accNum int) []sdk.AccAddress {
|
||||||
|
// createRandomAccounts is a strategy used by addTestAddrs() in order to generated addresses in random order.
|
||||||
|
testAddrs := make([]sdk.AccAddress, accNum)
|
||||||
|
for i := 0; i < accNum; i++ {
|
||||||
|
pk := ed25519.GenPrivKey().PubKey()
|
||||||
|
testAddrs[i] = sdk.AccAddress(pk.Address())
|
||||||
|
}
|
||||||
|
|
||||||
|
return testAddrs
|
||||||
|
}
|
||||||
|
@ -120,6 +120,9 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
|
|||||||
// add rosetta
|
// add rosetta
|
||||||
rootCmd.AddCommand(sdkserver.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Marshaler))
|
rootCmd.AddCommand(sdkserver.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Marshaler))
|
||||||
|
|
||||||
|
// Add flags for GQL server.
|
||||||
|
rootCmd = srvflags.AddGQLFlags(rootCmd)
|
||||||
|
|
||||||
return rootCmd, encodingConfig
|
return rootCmd, encodingConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,6 +231,8 @@ func (a appCreator) newApp(logger tmlog.Logger, db dbm.DB, traceStore io.Writer,
|
|||||||
baseapp.SetSnapshotKeepRecent(cast.ToUint32(appOpts.Get(sdkserver.FlagStateSyncSnapshotKeepRecent))),
|
baseapp.SetSnapshotKeepRecent(cast.ToUint32(appOpts.Get(sdkserver.FlagStateSyncSnapshotKeepRecent))),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Start
|
||||||
|
//go gql.Server(ethermintApp.BaseApp, ethermintApp.AppCodec(), ethermintApp.AccountKeeper, ethermintApp.BondKeeper)
|
||||||
return ethermintApp
|
return ethermintApp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
43
go.mod
43
go.mod
@ -3,19 +3,24 @@ module github.com/tharsis/ethermint
|
|||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/99designs/gqlgen v0.14.0
|
||||||
github.com/btcsuite/btcd v0.22.0-beta
|
github.com/btcsuite/btcd v0.22.0-beta
|
||||||
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
|
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
|
||||||
github.com/cosmos/cosmos-sdk v0.44.0
|
github.com/cosmos/cosmos-sdk v0.44.0
|
||||||
github.com/cosmos/go-bip39 v1.0.0
|
github.com/cosmos/go-bip39 v1.0.0
|
||||||
github.com/cosmos/ibc-go v1.2.0
|
github.com/cosmos/ibc-go v1.2.0
|
||||||
|
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea
|
||||||
github.com/ethereum/go-ethereum v1.10.3
|
github.com/ethereum/go-ethereum v1.10.3
|
||||||
|
github.com/gibson042/canonicaljson-go v1.0.3
|
||||||
github.com/gogo/protobuf v1.3.3
|
github.com/gogo/protobuf v1.3.3
|
||||||
github.com/golang/protobuf v1.5.2
|
github.com/golang/protobuf v1.5.2
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/gorilla/websocket v1.4.2
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0
|
||||||
github.com/improbable-eng/grpc-web v0.14.1
|
github.com/improbable-eng/grpc-web v0.14.1
|
||||||
|
github.com/ipfs/go-ipld-cbor v0.0.5
|
||||||
github.com/miguelmota/go-ethereum-hdwallet v0.0.1
|
github.com/miguelmota/go-ethereum-hdwallet v0.0.1
|
||||||
|
github.com/multiformats/go-multihash v0.0.10
|
||||||
github.com/palantir/stacktrace v0.0.0-20161112013806-78658fd2d177
|
github.com/palantir/stacktrace v0.0.0-20161112013806-78658fd2d177
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/rakyll/statik v0.1.7
|
github.com/rakyll/statik v0.1.7
|
||||||
@ -30,13 +35,16 @@ require (
|
|||||||
github.com/tendermint/tendermint v0.34.13
|
github.com/tendermint/tendermint v0.34.13
|
||||||
github.com/tendermint/tm-db v0.6.4
|
github.com/tendermint/tm-db v0.6.4
|
||||||
github.com/tyler-smith/go-bip39 v1.1.0
|
github.com/tyler-smith/go-bip39 v1.1.0
|
||||||
|
github.com/vektah/gqlparser/v2 v2.2.0
|
||||||
go.etcd.io/bbolt v1.3.6 // indirect
|
go.etcd.io/bbolt v1.3.6 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
|
||||||
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f // indirect
|
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f // indirect
|
||||||
golang.org/x/sys v0.0.0-20210903071746-97244b99971b // indirect
|
golang.org/x/sys v0.0.0-20210903071746-97244b99971b // indirect
|
||||||
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af
|
google.golang.org/genproto v0.0.0-20211013025323-ce878158c4d4
|
||||||
google.golang.org/grpc v1.40.0
|
google.golang.org/grpc v1.40.0
|
||||||
|
google.golang.org/protobuf v1.27.1
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@ -44,13 +52,10 @@ require (
|
|||||||
github.com/99designs/keyring v1.1.6 // indirect
|
github.com/99designs/keyring v1.1.6 // indirect
|
||||||
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
|
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
|
||||||
github.com/DataDog/zstd v1.4.8 // indirect
|
github.com/DataDog/zstd v1.4.8 // indirect
|
||||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
|
||||||
github.com/Masterminds/semver v1.5.0 // indirect
|
|
||||||
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
|
||||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
|
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
|
||||||
github.com/VictoriaMetrics/fastcache v1.5.7 // indirect
|
github.com/VictoriaMetrics/fastcache v1.5.7 // indirect
|
||||||
github.com/Workiva/go-datastructures v1.0.52 // indirect
|
github.com/Workiva/go-datastructures v1.0.52 // indirect
|
||||||
github.com/aokoli/goutils v1.1.1 // indirect
|
github.com/agnivade/levenshtein v1.1.0 // indirect
|
||||||
github.com/armon/go-metrics v0.3.9 // indirect
|
github.com/armon/go-metrics v0.3.9 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bgentry/speakeasy v0.1.0 // indirect
|
github.com/bgentry/speakeasy v0.1.0 // indirect
|
||||||
@ -63,7 +68,6 @@ require (
|
|||||||
github.com/cosmos/ledger-go v0.9.2 // indirect
|
github.com/cosmos/ledger-go v0.9.2 // indirect
|
||||||
github.com/danieljoos/wincred v1.0.2 // indirect
|
github.com/danieljoos/wincred v1.0.2 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea // indirect
|
|
||||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
||||||
github.com/dgraph-io/badger/v2 v2.2007.2 // indirect
|
github.com/dgraph-io/badger/v2 v2.2007.2 // indirect
|
||||||
github.com/dgraph-io/ristretto v0.0.3 // indirect
|
github.com/dgraph-io/ristretto v0.0.3 // indirect
|
||||||
@ -72,7 +76,6 @@ require (
|
|||||||
github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect
|
github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect
|
||||||
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
||||||
github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 // indirect
|
github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 // indirect
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.6.1 // indirect
|
|
||||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
|
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
|
||||||
@ -97,10 +100,12 @@ require (
|
|||||||
github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 // indirect
|
github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 // indirect
|
||||||
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
|
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
|
||||||
github.com/holiman/uint256 v1.1.1 // indirect
|
github.com/holiman/uint256 v1.1.1 // indirect
|
||||||
github.com/huandu/xstrings v1.3.2 // indirect
|
|
||||||
github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88 // indirect
|
github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88 // indirect
|
||||||
github.com/imdario/mergo v0.3.12 // indirect
|
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
|
github.com/ipfs/go-block-format v0.0.2 // indirect
|
||||||
|
github.com/ipfs/go-cid v0.0.3 // indirect
|
||||||
|
github.com/ipfs/go-ipfs-util v0.0.1 // indirect
|
||||||
|
github.com/ipfs/go-ipld-format v0.0.1 // indirect
|
||||||
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 // indirect
|
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 // indirect
|
||||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||||
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect
|
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect
|
||||||
@ -111,27 +116,29 @@ require (
|
|||||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||||
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect
|
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect
|
||||||
|
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
|
||||||
github.com/minio/highwayhash v1.0.1 // indirect
|
github.com/minio/highwayhash v1.0.1 // indirect
|
||||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
github.com/mr-tron/base58 v1.1.2 // indirect
|
||||||
github.com/mtibben/percent v0.2.1 // indirect
|
github.com/mtibben/percent v0.2.1 // indirect
|
||||||
github.com/mwitkow/go-proto-validators v0.3.2 // indirect
|
github.com/multiformats/go-base32 v0.0.3 // indirect
|
||||||
|
github.com/multiformats/go-multibase v0.0.1 // indirect
|
||||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||||
github.com/pelletier/go-toml v1.9.3 // indirect
|
github.com/pelletier/go-toml v1.9.3 // indirect
|
||||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
|
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992 // indirect
|
||||||
github.com/prometheus/client_golang v1.11.0 // indirect
|
github.com/prometheus/client_golang v1.11.0 // indirect
|
||||||
github.com/prometheus/client_model v0.2.0 // indirect
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
github.com/prometheus/common v0.29.0 // indirect
|
github.com/prometheus/common v0.29.0 // indirect
|
||||||
github.com/prometheus/procfs v0.6.0 // indirect
|
github.com/prometheus/procfs v0.6.0 // indirect
|
||||||
github.com/prometheus/tsdb v0.7.1 // indirect
|
github.com/prometheus/tsdb v0.7.1 // indirect
|
||||||
github.com/pseudomuto/protoc-gen-doc v1.5.0 // indirect
|
|
||||||
github.com/pseudomuto/protokit v0.2.0 // indirect
|
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||||
github.com/rjeczalik/notify v0.9.1 // indirect
|
github.com/rjeczalik/notify v0.9.1 // indirect
|
||||||
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect
|
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect
|
||||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
|
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||||
github.com/spf13/afero v1.6.0 // indirect
|
github.com/spf13/afero v1.6.0 // indirect
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
@ -143,15 +150,15 @@ require (
|
|||||||
github.com/tendermint/go-amino v0.16.0 // indirect
|
github.com/tendermint/go-amino v0.16.0 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.5 // indirect
|
github.com/tklauser/go-sysconf v0.3.5 // indirect
|
||||||
github.com/tklauser/numcpus v0.2.2 // indirect
|
github.com/tklauser/numcpus v0.2.2 // indirect
|
||||||
|
github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158 // indirect
|
||||||
github.com/zondax/hid v0.9.0 // indirect
|
github.com/zondax/hid v0.9.0 // indirect
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
|
||||||
golang.org/x/text v0.3.6 // indirect
|
golang.org/x/text v0.3.6 // indirect
|
||||||
google.golang.org/protobuf v1.27.1 // indirect
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
|
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
|
||||||
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 // indirect
|
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
|
||||||
nhooyr.io/websocket v1.8.6 // indirect
|
nhooyr.io/websocket v1.8.6 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -160,3 +167,5 @@ replace google.golang.org/grpc => google.golang.org/grpc v1.33.2
|
|||||||
replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
|
replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
|
||||||
|
|
||||||
replace github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76
|
replace github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76
|
||||||
|
|
||||||
|
replace github.com/cosmos/cosmos-sdk => github.com/vulcanize/cosmos-sdk v0.45.0-smt-alpha
|
||||||
|
122
go.sum
122
go.sum
@ -43,6 +43,8 @@ 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=
|
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 h1:/BZRNzm8N4K4eWfK28dL4yescorxtO7YG1yun8fy+pI=
|
||||||
filippo.io/edwards25519 v1.0.0-beta.2/go.mod h1:X+pm78QAUPtFLi1z9PYIlS/bdDnvbCOGKtZ+ACWEf7o=
|
filippo.io/edwards25519 v1.0.0-beta.2/go.mod h1:X+pm78QAUPtFLi1z9PYIlS/bdDnvbCOGKtZ+ACWEf7o=
|
||||||
|
github.com/99designs/gqlgen v0.14.0 h1:Wg8aNYQUjMR/4v+W3xD+7SizOy6lSvVeQ06AobNQAXI=
|
||||||
|
github.com/99designs/gqlgen v0.14.0/go.mod h1:S7z4boV+Nx4VvzMUpVrY/YuHjFX4n7rDyuTqvAkuoRE=
|
||||||
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
|
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
|
||||||
github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc=
|
github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc=
|
||||||
github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4=
|
github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4=
|
||||||
@ -71,14 +73,6 @@ github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t
|
|||||||
github.com/DataDog/zstd v1.4.8 h1:Rpmta4xZ/MgZnriKNd24iZMhGpP5dvUcs/uqfBapKZY=
|
github.com/DataDog/zstd v1.4.8 h1:Rpmta4xZ/MgZnriKNd24iZMhGpP5dvUcs/uqfBapKZY=
|
||||||
github.com/DataDog/zstd v1.4.8/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
github.com/DataDog/zstd v1.4.8/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
||||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
|
||||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
|
||||||
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
|
||||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
|
||||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
|
||||||
github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
|
|
||||||
github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
|
|
||||||
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
|
|
||||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||||
github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU=
|
github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU=
|
||||||
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
@ -102,6 +96,9 @@ github.com/adlio/schema v1.1.13 h1:LeNMVg5Z1FX+Qgz8tJUijBLRdcpbFUElz+d1489On98=
|
|||||||
github.com/adlio/schema v1.1.13/go.mod h1:L5Z7tw+7lRK1Fnpi/LT/ooCP1elkXn0krMWBQHUhEDE=
|
github.com/adlio/schema v1.1.13/go.mod h1:L5Z7tw+7lRK1Fnpi/LT/ooCP1elkXn0krMWBQHUhEDE=
|
||||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
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/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||||
|
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||||
|
github.com/agnivade/levenshtein v1.1.0 h1:n6qGwyHG61v3ABce1rPVZklEYRT8NFpCMrpZdBUbYGM=
|
||||||
|
github.com/agnivade/levenshtein v1.1.0/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
|
||||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
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-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
@ -111,14 +108,14 @@ 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-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 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc=
|
||||||
github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
||||||
|
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
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/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
|
|
||||||
github.com/aokoli/goutils v1.1.1 h1:/hA+Ywo3AxoDZY5ZMnkiEkUvkK4BPp927ax110KCqqg=
|
|
||||||
github.com/aokoli/goutils v1.1.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
|
|
||||||
github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0=
|
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.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
|
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
||||||
|
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
||||||
github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks=
|
github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks=
|
||||||
github.com/aristanetworks/glog v0.0.0-20191112221043-67e8567f59f3/go.mod h1:KASm+qXFKs/xjSoWn30NrWBBvdTTQq+UjkhjEJHfSFA=
|
github.com/aristanetworks/glog v0.0.0-20191112221043-67e8567f59f3/go.mod h1:KASm+qXFKs/xjSoWn30NrWBBvdTTQq+UjkhjEJHfSFA=
|
||||||
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
|
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
|
||||||
@ -254,7 +251,6 @@ github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2
|
|||||||
github.com/danieljoos/wincred v1.0.2 h1:zf4bhty2iLuwgjgpraD2E9UbvO+fe54XXGJbOwe23fU=
|
github.com/danieljoos/wincred v1.0.2 h1:zf4bhty2iLuwgjgpraD2E9UbvO+fe54XXGJbOwe23fU=
|
||||||
github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U=
|
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/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
|
||||||
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
@ -276,6 +272,8 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn
|
|||||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
|
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-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/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
|
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g=
|
||||||
|
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
|
||||||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
github.com/dlclark/regexp2 v1.2.0/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/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-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||||
@ -302,9 +300,6 @@ github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 h1:2vLKys4RBU4
|
|||||||
github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25/go.mod h1:hTr8+TLQmkUkgcuh3mcr5fjrT9c64ZzsBCdCEC6UppY=
|
github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25/go.mod h1:hTr8+TLQmkUkgcuh3mcr5fjrT9c64ZzsBCdCEC6UppY=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
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/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.3.0-java/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.6.1 h1:4CF52PCseTFt4bE+Yk3dIpdVi7XWuPVMhPtm4FaIJPM=
|
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.6.1/go.mod h1:txg5va2Qkip90uYoSKH+nkAAmXrb2j3iq4FLwdrCbXQ=
|
|
||||||
github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM=
|
github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM=
|
||||||
github.com/ethereum/go-ethereum v1.10.1/go.mod h1:E5e/zvdfUVr91JZ0AwjyuJM3x+no51zZJRz61orLLSk=
|
github.com/ethereum/go-ethereum v1.10.1/go.mod h1:E5e/zvdfUVr91JZ0AwjyuJM3x+no51zZJRz61orLLSk=
|
||||||
github.com/ethereum/go-ethereum v1.10.3 h1:SEYOYARvbWnoDl1hOSks3ZJQpRiiRJe8ubaQGJQwq0s=
|
github.com/ethereum/go-ethereum v1.10.3 h1:SEYOYARvbWnoDl1hOSks3ZJQpRiiRJe8ubaQGJQwq0s=
|
||||||
@ -336,6 +331,8 @@ github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05
|
|||||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
|
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/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/gibson042/canonicaljson-go v1.0.3 h1:EAyF8L74AWabkyUmrvEFHEt/AGFQeD6RfwbAuf0j1bI=
|
||||||
|
github.com/gibson042/canonicaljson-go v1.0.3/go.mod h1:DsLpJTThXyGNO+KZlI85C1/KDcImpP67k/RKVjcaEqo=
|
||||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
|
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
|
||||||
@ -464,7 +461,6 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe
|
|||||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/protobuf v3.14.0+incompatible/go.mod h1:lUQ9D1ePzbH2PrIS7ob/bjm9HXyH5WHB0Akwh7URreM=
|
github.com/google/protobuf v3.14.0+incompatible/go.mod h1:lUQ9D1ePzbH2PrIS7ob/bjm9HXyH5WHB0Akwh7URreM=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
||||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
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.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.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
@ -476,9 +472,11 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
|
|||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
|
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
|
||||||
|
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||||
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
|
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
|
||||||
|
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
@ -514,6 +512,8 @@ github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is=
|
|||||||
github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s=
|
github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s=
|
||||||
github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc=
|
github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc=
|
||||||
github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o=
|
github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o=
|
||||||
|
github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
|
||||||
|
github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
|
||||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||||
@ -553,21 +553,14 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iU
|
|||||||
github.com/holiman/uint256 v1.1.1 h1:4JywC80b+/hSfljFlEBLHrrh+CIONLDz9NuFl0af4Mw=
|
github.com/holiman/uint256 v1.1.1 h1:4JywC80b+/hSfljFlEBLHrrh+CIONLDz9NuFl0af4Mw=
|
||||||
github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
|
github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo=
|
|
||||||
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
|
|
||||||
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
|
||||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
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.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
|
||||||
github.com/huin/goupnp v1.0.1-0.20200620063722-49508fba0031/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo=
|
github.com/huin/goupnp v1.0.1-0.20200620063722-49508fba0031/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo=
|
||||||
github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88 h1:bcAj8KroPf552TScjFPIakjH2/tdIrIH8F+cc4v4SRo=
|
github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88 h1:bcAj8KroPf552TScjFPIakjH2/tdIrIH8F+cc4v4SRo=
|
||||||
github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo=
|
github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo=
|
||||||
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
|
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
|
||||||
github.com/iancoleman/strcase v0.0.0-20180726023541-3605ed457bf7/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE=
|
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
|
||||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
|
||||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
|
||||||
github.com/improbable-eng/grpc-web v0.14.0/go.mod h1:6hRR09jOEG81ADP5wCQju1z71g6OL4eEvELdran/3cs=
|
github.com/improbable-eng/grpc-web v0.14.0/go.mod h1:6hRR09jOEG81ADP5wCQju1z71g6OL4eEvELdran/3cs=
|
||||||
github.com/improbable-eng/grpc-web v0.14.1 h1:NrN4PY71A6tAz2sKDvC5JCauENWp0ykG8Oq1H3cpFvw=
|
github.com/improbable-eng/grpc-web v0.14.1 h1:NrN4PY71A6tAz2sKDvC5JCauENWp0ykG8Oq1H3cpFvw=
|
||||||
github.com/improbable-eng/grpc-web v0.14.1/go.mod h1:zEjGHa8DAlkoOXmswrNvhUGEYQA9UI7DhrGeHR1DMGU=
|
github.com/improbable-eng/grpc-web v0.14.1/go.mod h1:zEjGHa8DAlkoOXmswrNvhUGEYQA9UI7DhrGeHR1DMGU=
|
||||||
@ -584,6 +577,17 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y
|
|||||||
github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE=
|
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/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/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po=
|
||||||
|
github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE=
|
||||||
|
github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY=
|
||||||
|
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
|
||||||
|
github.com/ipfs/go-cid v0.0.3 h1:UIAh32wymBpStoe83YCzwVQQ5Oy/H0FdxvUS6DJDzms=
|
||||||
|
github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
|
||||||
|
github.com/ipfs/go-ipfs-util v0.0.1 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50=
|
||||||
|
github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc=
|
||||||
|
github.com/ipfs/go-ipld-cbor v0.0.5 h1:ovz4CHKogtG2KB/h1zUp5U0c/IzZrL435rCh5+K/5G8=
|
||||||
|
github.com/ipfs/go-ipld-cbor v0.0.5/go.mod h1:BkCduEx3XBCO6t2Sfo5BaHzuok7hbhdMm9Oh8B2Ftq4=
|
||||||
|
github.com/ipfs/go-ipld-format v0.0.1 h1:HCu4eB/Gh+KD/Q0M8u888RFkorTWNIL3da4oc5dwc80=
|
||||||
|
github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms=
|
||||||
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 h1:6OvNmYgJyexcZ3pYbTI9jWx5tHo1Dee/tWbLMfPe2TA=
|
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 h1:6OvNmYgJyexcZ3pYbTI9jWx5tHo1Dee/tWbLMfPe2TA=
|
||||||
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||||
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
|
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
|
||||||
@ -615,6 +619,7 @@ github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/
|
|||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
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/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/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o=
|
||||||
|
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
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.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
@ -668,14 +673,16 @@ github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOS
|
|||||||
github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM=
|
github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM=
|
||||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||||
|
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||||
github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4=
|
github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4=
|
||||||
github.com/lyft/protoc-gen-star v0.5.1/go.mod h1:9toiA3cC7z5uVbODF7kEQ91Xn7XNFkVUl+SrEe+ZORU=
|
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
||||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||||
|
github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/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.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.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
|
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
|
||||||
@ -683,6 +690,7 @@ github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HN
|
|||||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
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.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.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.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.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
|
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
|
||||||
@ -701,23 +709,25 @@ github.com/miguelmota/go-ethereum-hdwallet v0.0.1 h1:DWqgZtKWTGcHR5QsprMJItZiJ2x
|
|||||||
github.com/miguelmota/go-ethereum-hdwallet v0.0.1/go.mod h1:iowKavXnc0NVNiv/UKYYBo3SjADph5PUvYQTjOIV9as=
|
github.com/miguelmota/go-ethereum-hdwallet v0.0.1/go.mod h1:iowKavXnc0NVNiv/UKYYBo3SjADph5PUvYQTjOIV9as=
|
||||||
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0=
|
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-20181016162300-f8f6d4d2b643/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.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0=
|
github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0=
|
||||||
github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
|
github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
|
||||||
|
github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
|
||||||
|
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo=
|
||||||
|
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
|
||||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
|
||||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/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.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
||||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
|
||||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
|
||||||
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
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 h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
@ -725,16 +735,23 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
|||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
|
||||||
|
github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78=
|
||||||
|
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||||
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
|
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
|
||||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
|
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 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs=
|
||||||
github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns=
|
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=
|
||||||
|
github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
|
||||||
|
github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA=
|
||||||
|
github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
|
||||||
|
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
|
||||||
|
github.com/multiformats/go-multihash v0.0.10 h1:lMoNbh2Ssd9PUF74Nz008KGzGPlfeV6wH3rit5IIGCM=
|
||||||
|
github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
|
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo=
|
|
||||||
github.com/mwitkow/go-proto-validators v0.3.2 h1:qRlmpTzm2pstMKKzTdvwPCF5QfBNURSlAgN/R+qbKos=
|
|
||||||
github.com/mwitkow/go-proto-validators v0.3.2/go.mod h1:ej0Qp0qMgHN/KtDyUt+Q1/tA7a5VarXUOUxD+oeD30w=
|
|
||||||
github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo=
|
github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo=
|
||||||
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
|
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
|
||||||
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
|
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
|
||||||
@ -831,9 +848,10 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
|||||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||||
github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
|
github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
|
||||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992 h1:bzMe+2coZJYHnhGgVlcQKuRy4FSny4ds8dLQjw5P1XE=
|
||||||
|
github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o=
|
||||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||||
@ -880,10 +898,6 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
|
|||||||
github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
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 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/pseudomuto/protoc-gen-doc v1.5.0 h1:pHZp0MEiT68jrZV8js8BS7E9ZEnlSLegoQbbtXj5lfo=
|
|
||||||
github.com/pseudomuto/protoc-gen-doc v1.5.0/go.mod h1:exDTOVwqpp30eV/EDPFLZy3Pwr2sn6hBC1WIYH/UbIg=
|
|
||||||
github.com/pseudomuto/protokit v0.2.0 h1:hlnBDcy3YEDXH7kc9gV+NLaN0cDzhDvD1s7Y6FZ8RpM=
|
|
||||||
github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q=
|
|
||||||
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
|
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
|
||||||
github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc=
|
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-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
@ -901,6 +915,7 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So
|
|||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||||
|
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||||
github.com/rs/cors v1.8.0 h1:P2KMzcFwrPoSjkF1WLRPsp3UMLyql8L4v9hQpVeK5so=
|
github.com/rs/cors v1.8.0 h1:P2KMzcFwrPoSjkF1WLRPsp3UMLyql8L4v9hQpVeK5so=
|
||||||
github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM=
|
github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM=
|
||||||
@ -924,10 +939,14 @@ github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KR
|
|||||||
github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
|
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/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/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
|
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||||
|
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
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 h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
|
||||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
|
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
|
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
@ -937,6 +956,7 @@ github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE
|
|||||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
|
github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU=
|
||||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4=
|
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4=
|
||||||
@ -946,8 +966,6 @@ 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 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
|
|
||||||
github.com/spf13/afero v1.3.4/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
|
||||||
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
|
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
|
||||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
@ -987,8 +1005,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
|
||||||
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
@ -1048,11 +1066,19 @@ 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/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.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
|
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||||
|
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
|
||||||
|
github.com/vektah/gqlparser/v2 v2.2.0 h1:bAc3slekAAJW6sZTi07aGq0OrfaCjj4jxARAaC7g2EM=
|
||||||
|
github.com/vektah/gqlparser/v2 v2.2.0/go.mod h1:i3mQIGIrbK2PD1RrCeMTlVbkF2FJ6WkU1KJlJlC+3F4=
|
||||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||||
github.com/vmihailenco/msgpack/v5 v5.1.4/go.mod h1:C5gboKD0TJPqWDTVTtrQNfRbiBwHZGo8UTqP/9/XvLI=
|
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/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||||
|
github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436 h1:qOpVTI+BrstcjTZLm2Yz/3sOnqkzj3FQoh0g+E5s3Gc=
|
||||||
|
github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
|
||||||
|
github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158 h1:WXhVOwj2USAXB5oMDwRl3piOux2XMV9TANaYxXHdkoE=
|
||||||
|
github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI=
|
||||||
github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
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/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees=
|
||||||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||||
@ -1101,14 +1127,15 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
|||||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
@ -1128,8 +1155,8 @@ golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWP
|
|||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
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-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-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
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/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
@ -1245,7 +1272,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -1265,6 +1291,8 @@ 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-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-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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190219092855-153ac476189d/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-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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -1362,6 +1390,7 @@ golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiT
|
|||||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/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-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-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/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-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-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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
@ -1370,6 +1399,7 @@ golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3
|
|||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
@ -1464,7 +1494,6 @@ google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID
|
|||||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20181107211654-5fc9ac540362/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
@ -1513,8 +1542,8 @@ google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6D
|
|||||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||||
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af h1:aLMMXFYqw01RA6XJim5uaN+afqNNjc9P8HPAbnpnc5s=
|
google.golang.org/genproto v0.0.0-20211013025323-ce878158c4d4 h1:NBxB1XxiWpGqkPUiJ9PoBXkHV5A9+GohMOA+EmWoPbU=
|
||||||
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
google.golang.org/genproto v0.0.0-20211013025323-ce878158c4d4/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o=
|
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/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.1/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.1/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||||
@ -1597,3 +1626,4 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
|||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||||
|
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=
|
||||||
|
351
gql/README.md
Normal file
351
gql/README.md
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
# Vulcanize dxns gql
|
||||||
|
|
||||||
|
> Browser : http://localhost:9473 for gql
|
||||||
|
|
||||||
|
## Start server
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./build/ethermintd start --gql-playground --gql-server
|
||||||
|
```
|
||||||
|
|
||||||
|
Basic node status:
|
||||||
|
|
||||||
|
```graphql
|
||||||
|
{
|
||||||
|
getStatus {
|
||||||
|
version
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
network
|
||||||
|
moniker
|
||||||
|
}
|
||||||
|
sync {
|
||||||
|
latest_block_height
|
||||||
|
catching_up
|
||||||
|
}
|
||||||
|
num_peers
|
||||||
|
peers {
|
||||||
|
is_outbound
|
||||||
|
remote_ip
|
||||||
|
}
|
||||||
|
disk_usage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Full node status:
|
||||||
|
|
||||||
|
```graphql
|
||||||
|
{
|
||||||
|
getStatus {
|
||||||
|
version
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
network
|
||||||
|
moniker
|
||||||
|
}
|
||||||
|
sync {
|
||||||
|
latest_block_hash
|
||||||
|
latest_block_time
|
||||||
|
latest_block_height
|
||||||
|
catching_up
|
||||||
|
}
|
||||||
|
validator {
|
||||||
|
address
|
||||||
|
voting_power
|
||||||
|
proposer_priority
|
||||||
|
}
|
||||||
|
validators {
|
||||||
|
address
|
||||||
|
voting_power
|
||||||
|
proposer_priority
|
||||||
|
}
|
||||||
|
num_peers
|
||||||
|
peers {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
network
|
||||||
|
moniker
|
||||||
|
}
|
||||||
|
is_outbound
|
||||||
|
remote_ip
|
||||||
|
}
|
||||||
|
disk_usage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Get records by IDs.
|
||||||
|
|
||||||
|
```graphql
|
||||||
|
{
|
||||||
|
getRecordsByIds(ids: ["QmYDtNCKtTu6u6jaHaFAC5PWZXcj7fAmry6NoWwMaixFHz"]) {
|
||||||
|
id
|
||||||
|
names
|
||||||
|
bondId
|
||||||
|
createTime
|
||||||
|
expiryTime
|
||||||
|
owners
|
||||||
|
attributes {
|
||||||
|
key
|
||||||
|
value {
|
||||||
|
string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Query records.
|
||||||
|
|
||||||
|
```graphql
|
||||||
|
{
|
||||||
|
queryRecords(attributes: [{ key: "type", value: { string: "wrn:bot" } }]) {
|
||||||
|
id
|
||||||
|
names
|
||||||
|
bondId
|
||||||
|
createTime
|
||||||
|
expiryTime
|
||||||
|
owners
|
||||||
|
attributes {
|
||||||
|
key
|
||||||
|
value {
|
||||||
|
string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Get account details:
|
||||||
|
|
||||||
|
```graphql
|
||||||
|
{
|
||||||
|
getAccounts(addresses: ["cosmos1wh8vvd0ymc5nt37h29z8kk2g2ays45ct2qu094"]) {
|
||||||
|
address
|
||||||
|
pubKey
|
||||||
|
number
|
||||||
|
sequence
|
||||||
|
balance {
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Query bonds:
|
||||||
|
|
||||||
|
```graphql
|
||||||
|
{
|
||||||
|
queryBonds(
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
key: "owner"
|
||||||
|
value: { string: "cosmos1wh8vvd0ymc5nt37h29z8kk2g2ays45ct2qu094" }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
owner
|
||||||
|
balance {
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Get bonds by IDs.
|
||||||
|
|
||||||
|
```graphql
|
||||||
|
{
|
||||||
|
getBondsByIds(ids :
|
||||||
|
[
|
||||||
|
"1c2b677cb2a27c88cc6bf8acf675c94b69051125b40c4fd073153b10f046dd87",
|
||||||
|
"c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440"
|
||||||
|
])
|
||||||
|
{
|
||||||
|
id
|
||||||
|
owner
|
||||||
|
balance{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Query Bonds by Owner
|
||||||
|
|
||||||
|
```graphql
|
||||||
|
{
|
||||||
|
queryBondsByOwner(ownerAddresses: ["ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk"])
|
||||||
|
{
|
||||||
|
owner
|
||||||
|
bonds{
|
||||||
|
id
|
||||||
|
owner
|
||||||
|
balance
|
||||||
|
{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Query auctions by ids
|
||||||
|
|
||||||
|
```graphql
|
||||||
|
{
|
||||||
|
getAuctionsByIds(ids: ["be98f2073c246194276554eefdb4c95b682a35a0f06fbe619a6da57c10c93e90"]){
|
||||||
|
id
|
||||||
|
ownerAddress
|
||||||
|
createTime
|
||||||
|
minimumBid{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
commitFee{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
commitsEndTime
|
||||||
|
revealFee{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
revealsEndTime
|
||||||
|
winnerBid{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
winnerPrice{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
winnerAddress
|
||||||
|
bids{
|
||||||
|
bidderAddress
|
||||||
|
commitHash
|
||||||
|
commitTime
|
||||||
|
commitFee{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
revealFee{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
revealTime
|
||||||
|
bidAmount{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
LookUp Authorities
|
||||||
|
|
||||||
|
```graphql
|
||||||
|
{
|
||||||
|
lookupAuthorities(names: []){
|
||||||
|
ownerAddress
|
||||||
|
ownerAddress
|
||||||
|
height
|
||||||
|
bondId
|
||||||
|
status
|
||||||
|
expiryTime
|
||||||
|
auction {
|
||||||
|
id
|
||||||
|
ownerAddress
|
||||||
|
createTime
|
||||||
|
minimumBid{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
commitFee{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
commitsEndTime
|
||||||
|
revealFee{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
revealsEndTime
|
||||||
|
winnerBid{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
winnerPrice{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
winnerAddress
|
||||||
|
bids{
|
||||||
|
bidderAddress
|
||||||
|
commitHash
|
||||||
|
commitTime
|
||||||
|
commitFee{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
revealFee{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
revealTime
|
||||||
|
bidAmount{
|
||||||
|
type
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
LookUp Names
|
||||||
|
|
||||||
|
```graphql
|
||||||
|
{
|
||||||
|
lookupNames(names: ["wrn://hello/test"]){
|
||||||
|
latest{
|
||||||
|
id
|
||||||
|
height
|
||||||
|
}
|
||||||
|
history{
|
||||||
|
id
|
||||||
|
height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Resolve Names
|
||||||
|
|
||||||
|
```graphql
|
||||||
|
{
|
||||||
|
resolveNames(names: ["asd"]){
|
||||||
|
id
|
||||||
|
names
|
||||||
|
bondId
|
||||||
|
createTime
|
||||||
|
expiryTime
|
||||||
|
owners
|
||||||
|
attributes {
|
||||||
|
key
|
||||||
|
value {
|
||||||
|
string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
8781
gql/generated.go
Normal file
8781
gql/generated.go
Normal file
File diff suppressed because it is too large
Load Diff
14
gql/gqlgen.yml
Normal file
14
gql/gqlgen.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# .gqlgen.yml example
|
||||||
|
#
|
||||||
|
# Refer to https://gqlgen.com/config/
|
||||||
|
# for detailed .gqlgen.yml documentation.
|
||||||
|
|
||||||
|
schema:
|
||||||
|
- vulcanize/dxns/*.graphql
|
||||||
|
exec:
|
||||||
|
filename: generated.go
|
||||||
|
model:
|
||||||
|
filename: models_gen.go
|
||||||
|
resolver:
|
||||||
|
filename: resolver.go
|
||||||
|
type: Resolver
|
160
gql/models_gen.go
Normal file
160
gql/models_gen.go
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gql
|
||||||
|
|
||||||
|
type Account struct {
|
||||||
|
Address string `json:"address"`
|
||||||
|
PubKey *string `json:"pubKey"`
|
||||||
|
Number string `json:"number"`
|
||||||
|
Sequence string `json:"sequence"`
|
||||||
|
Balance []*Coin `json:"balance"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Auction struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
OwnerAddress string `json:"ownerAddress"`
|
||||||
|
CreateTime string `json:"createTime"`
|
||||||
|
CommitsEndTime string `json:"commitsEndTime"`
|
||||||
|
RevealsEndTime string `json:"revealsEndTime"`
|
||||||
|
CommitFee *Coin `json:"commitFee"`
|
||||||
|
RevealFee *Coin `json:"revealFee"`
|
||||||
|
MinimumBid *Coin `json:"minimumBid"`
|
||||||
|
WinnerAddress string `json:"winnerAddress"`
|
||||||
|
WinnerBid *Coin `json:"winnerBid"`
|
||||||
|
WinnerPrice *Coin `json:"winnerPrice"`
|
||||||
|
Bids []*AuctionBid `json:"bids"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuctionBid struct {
|
||||||
|
BidderAddress string `json:"bidderAddress"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
CommitHash string `json:"commitHash"`
|
||||||
|
CommitTime string `json:"commitTime"`
|
||||||
|
CommitFee *Coin `json:"commitFee"`
|
||||||
|
RevealTime string `json:"revealTime"`
|
||||||
|
RevealFee *Coin `json:"revealFee"`
|
||||||
|
BidAmount *Coin `json:"bidAmount"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthorityRecord struct {
|
||||||
|
OwnerAddress string `json:"ownerAddress"`
|
||||||
|
OwnerPublicKey string `json:"ownerPublicKey"`
|
||||||
|
Height string `json:"height"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
BondID string `json:"bondId"`
|
||||||
|
ExpiryTime string `json:"expiryTime"`
|
||||||
|
Auction *Auction `json:"auction"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bond struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Owner string `json:"owner"`
|
||||||
|
Balance []*Coin `json:"balance"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Coin struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Quantity string `json:"quantity"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeyValue struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value *Value `json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeyValueInput struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value *ValueInput `json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type NameRecord struct {
|
||||||
|
Latest *NameRecordEntry `json:"latest"`
|
||||||
|
History []*NameRecordEntry `json:"history"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type NameRecordEntry struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Height string `json:"height"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type NodeInfo struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Network string `json:"network"`
|
||||||
|
Moniker string `json:"moniker"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OwnerBonds struct {
|
||||||
|
Owner string `json:"owner"`
|
||||||
|
Bonds []*Bond `json:"bonds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PeerInfo struct {
|
||||||
|
Node *NodeInfo `json:"node"`
|
||||||
|
IsOutbound bool `json:"is_outbound"`
|
||||||
|
RemoteIP string `json:"remote_ip"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Record struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Names []string `json:"names"`
|
||||||
|
BondID string `json:"bondId"`
|
||||||
|
CreateTime string `json:"createTime"`
|
||||||
|
ExpiryTime string `json:"expiryTime"`
|
||||||
|
Owners []string `json:"owners"`
|
||||||
|
Attributes []*KeyValue `json:"attributes"`
|
||||||
|
References []*Record `json:"references"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Reference struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReferenceInput struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Status struct {
|
||||||
|
Version string `json:"version"`
|
||||||
|
Node *NodeInfo `json:"node"`
|
||||||
|
Sync *SyncInfo `json:"sync"`
|
||||||
|
Validator *ValidatorInfo `json:"validator"`
|
||||||
|
Validators []*ValidatorInfo `json:"validators"`
|
||||||
|
NumPeers string `json:"num_peers"`
|
||||||
|
Peers []*PeerInfo `json:"peers"`
|
||||||
|
DiskUsage string `json:"disk_usage"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SyncInfo struct {
|
||||||
|
LatestBlockHash string `json:"latest_block_hash"`
|
||||||
|
LatestBlockHeight string `json:"latest_block_height"`
|
||||||
|
LatestBlockTime string `json:"latest_block_time"`
|
||||||
|
CatchingUp bool `json:"catching_up"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ValidatorInfo struct {
|
||||||
|
Address string `json:"address"`
|
||||||
|
VotingPower string `json:"voting_power"`
|
||||||
|
ProposerPriority *string `json:"proposer_priority"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Value struct {
|
||||||
|
Null *bool `json:"null"`
|
||||||
|
Int *int `json:"int"`
|
||||||
|
Float *float64 `json:"float"`
|
||||||
|
String *string `json:"string"`
|
||||||
|
Boolean *bool `json:"boolean"`
|
||||||
|
JSON *string `json:"json"`
|
||||||
|
Reference *Reference `json:"reference"`
|
||||||
|
Values []*Value `json:"values"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ValueInput struct {
|
||||||
|
Null *bool `json:"null"`
|
||||||
|
Int *int `json:"int"`
|
||||||
|
Float *float64 `json:"float"`
|
||||||
|
String *string `json:"string"`
|
||||||
|
Boolean *bool `json:"boolean"`
|
||||||
|
Reference *ReferenceInput `json:"reference"`
|
||||||
|
Values []*ValueInput `json:"values"`
|
||||||
|
}
|
335
gql/resolver.go
Normal file
335
gql/resolver.go
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
package gql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/base64"
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
|
auctiontypes "github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
bondtypes "github.com/tharsis/ethermint/x/bond/types"
|
||||||
|
nstypes "github.com/tharsis/ethermint/x/nameservice/types"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultLogNumLines is the number of log lines to tail by default.
|
||||||
|
const DefaultLogNumLines = 50
|
||||||
|
|
||||||
|
// MaxLogNumLines is the max number of log lines that can be tailed.
|
||||||
|
const MaxLogNumLines = 1000
|
||||||
|
|
||||||
|
type Resolver struct {
|
||||||
|
ctx client.Context
|
||||||
|
logFile string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query is the entry point to query execution.
|
||||||
|
func (r *Resolver) Query() QueryResolver {
|
||||||
|
return &queryResolver{r}
|
||||||
|
}
|
||||||
|
|
||||||
|
type queryResolver struct{ *Resolver }
|
||||||
|
|
||||||
|
func (q queryResolver) LookupAuthorities(ctx context.Context, names []string) ([]*AuthorityRecord, error) {
|
||||||
|
nsQueryClient := nstypes.NewQueryClient(q.ctx)
|
||||||
|
auctionQueryClient := auctiontypes.NewQueryClient(q.ctx)
|
||||||
|
var gqlResponse []*AuthorityRecord
|
||||||
|
|
||||||
|
for _, name := range names {
|
||||||
|
res, err := nsQueryClient.Whois(context.Background(), &nstypes.QueryWhoisRequest{Name: name})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nameAuthority := res.GetNameAuthority()
|
||||||
|
gqlNameAuthorityRecord, err := GetGQLNameAuthorityRecord(&nameAuthority)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if nameAuthority.AuctionId == "" {
|
||||||
|
auctionResp, err := auctionQueryClient.GetAuction(context.Background(), &auctiontypes.AuctionRequest{Id: nameAuthority.GetAuctionId()})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bidsResp, err := auctionQueryClient.GetBids(context.Background(), &auctiontypes.BidsRequest{AuctionId: nameAuthority.GetAuctionId()})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gqlAuctionRecord, err := GetGQLAuction(auctionResp.GetAuction(), bidsResp.GetBids())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gqlNameAuthorityRecord.Auction = gqlAuctionRecord
|
||||||
|
}
|
||||||
|
|
||||||
|
gqlResponse = append(gqlResponse, gqlNameAuthorityRecord)
|
||||||
|
}
|
||||||
|
|
||||||
|
return gqlResponse, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q queryResolver) ResolveNames(ctx context.Context, names []string) ([]*Record, error) {
|
||||||
|
nsQueryClient := nstypes.NewQueryClient(q.ctx)
|
||||||
|
var gqlResponse []*Record
|
||||||
|
for _, name := range names {
|
||||||
|
res, err := nsQueryClient.ResolveWrn(context.Background(), &nstypes.QueryResolveWrn{Wrn: name})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gqlRecord, err := getGQLRecord(context.Background(), q, *res.GetRecord())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gqlResponse = append(gqlResponse, gqlRecord)
|
||||||
|
}
|
||||||
|
|
||||||
|
return gqlResponse, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q queryResolver) LookupNames(ctx context.Context, names []string) ([]*NameRecord, error) {
|
||||||
|
nsQueryClient := nstypes.NewQueryClient(q.ctx)
|
||||||
|
var gqlResponse []*NameRecord
|
||||||
|
|
||||||
|
for _, name := range names {
|
||||||
|
res, err := nsQueryClient.LookupWrn(context.Background(), &nstypes.QueryLookupWrn{Wrn: name})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gqlRecord, err := getGQLNameRecord(res.GetName())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gqlResponse = append(gqlResponse, gqlRecord)
|
||||||
|
}
|
||||||
|
|
||||||
|
return gqlResponse, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q queryResolver) QueryRecords(ctx context.Context, attributes []*KeyValueInput, all *bool) ([]*Record, error) {
|
||||||
|
nsQueryClient := nstypes.NewQueryClient(q.ctx)
|
||||||
|
res, err := nsQueryClient.ListRecords(context.Background(), &nstypes.QueryListRecordsRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
records := res.GetRecords()
|
||||||
|
gqlResponse := make([]*Record, len(records))
|
||||||
|
|
||||||
|
for i, record := range records {
|
||||||
|
gqlRecord, err := getGQLRecord(context.Background(), q, record)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
gqlResponse[i] = gqlRecord
|
||||||
|
}
|
||||||
|
|
||||||
|
return gqlResponse, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q queryResolver) GetRecordsByIds(ctx context.Context, ids []string) ([]*Record, error) {
|
||||||
|
nsQueryClient := nstypes.NewQueryClient(q.ctx)
|
||||||
|
gqlResponse := make([]*Record, len(ids))
|
||||||
|
|
||||||
|
for i, id := range ids {
|
||||||
|
res, err := nsQueryClient.GetRecord(context.Background(), &nstypes.QueryRecordByIdRequest{Id: id})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
record, err := getGQLRecord(context.Background(), q, res.GetRecord())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
gqlResponse[i] = record
|
||||||
|
}
|
||||||
|
|
||||||
|
return gqlResponse, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q queryResolver) GetStatus(ctx context.Context) (*Status, error) {
|
||||||
|
nodeInfo, syncInfo, validatorInfo, err := getStatusInfo(q.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
numPeers, peers, err := getNetInfo(q.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
validatorSet, err := getValidatorSet(q.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
diskUsage, err := GetDiskUsage(NodeDataPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Status{
|
||||||
|
Version: NameServiceVersion,
|
||||||
|
Node: nodeInfo,
|
||||||
|
Sync: syncInfo,
|
||||||
|
Validator: validatorInfo,
|
||||||
|
Validators: validatorSet,
|
||||||
|
NumPeers: numPeers,
|
||||||
|
Peers: peers,
|
||||||
|
DiskUsage: diskUsage,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q queryResolver) GetAccounts(ctx context.Context, addresses []string) ([]*Account, error) {
|
||||||
|
accounts := make([]*Account, len(addresses))
|
||||||
|
for index, address := range addresses {
|
||||||
|
account, err := q.GetAccount(ctx, address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
accounts[index] = account
|
||||||
|
}
|
||||||
|
return accounts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q queryResolver) GetAccount(ctx context.Context, address string) (*Account, error) {
|
||||||
|
authQueryClient := authtypes.NewQueryClient(q.ctx)
|
||||||
|
accountResponse, err := authQueryClient.Account(ctx, &authtypes.QueryAccountRequest{Address: address})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var account authtypes.AccountI
|
||||||
|
err = q.ctx.Codec.UnpackAny(accountResponse.GetAccount(), &account)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var pubKey *string
|
||||||
|
if account.GetPubKey() != nil {
|
||||||
|
pubKeyStr := base64.StdEncoding.EncodeToString(account.GetPubKey().Bytes())
|
||||||
|
pubKey = &pubKeyStr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the account balance
|
||||||
|
bankQueryClient := banktypes.NewQueryClient(q.ctx)
|
||||||
|
balance, err := bankQueryClient.AllBalances(ctx, &banktypes.QueryAllBalancesRequest{Address: address})
|
||||||
|
|
||||||
|
accNum := strconv.FormatUint(account.GetAccountNumber(), 10)
|
||||||
|
seq := strconv.FormatUint(account.GetSequence(), 10)
|
||||||
|
|
||||||
|
return &Account{
|
||||||
|
Address: address,
|
||||||
|
Number: accNum,
|
||||||
|
Sequence: seq,
|
||||||
|
PubKey: pubKey,
|
||||||
|
Balance: getGQLCoins(balance.GetBalances()),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q queryResolver) GetBondsByIds(ctx context.Context, ids []string) ([]*Bond, error) {
|
||||||
|
bonds := make([]*Bond, len(ids))
|
||||||
|
for index, id := range ids {
|
||||||
|
bondObj, err := q.GetBond(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bonds[index] = bondObj
|
||||||
|
}
|
||||||
|
|
||||||
|
return bonds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *queryResolver) GetBond(ctx context.Context, id string) (*Bond, error) {
|
||||||
|
bondQueryClient := bondtypes.NewQueryClient(q.ctx)
|
||||||
|
bondResp, err := bondQueryClient.GetBondById(context.Background(), &bondtypes.QueryGetBondByIdRequest{Id: id})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bond := bondResp.GetBond()
|
||||||
|
if bond == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return getGQLBond(bondResp.GetBond())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q queryResolver) QueryBonds(ctx context.Context, attributes []*KeyValueInput) ([]*Bond, error) {
|
||||||
|
bondQueryClient := bondtypes.NewQueryClient(q.ctx)
|
||||||
|
bonds, err := bondQueryClient.Bonds(context.Background(), &bondtypes.QueryGetBondsRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gqlResponse := make([]*Bond, len(bonds.GetBonds()))
|
||||||
|
for i, bondObj := range bonds.GetBonds() {
|
||||||
|
gqlBond, err := getGQLBond(bondObj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
gqlResponse[i] = gqlBond
|
||||||
|
}
|
||||||
|
|
||||||
|
return gqlResponse, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryBondsByOwner will return bonds by owner
|
||||||
|
func (q queryResolver) QueryBondsByOwner(ctx context.Context, ownerAddresses []string) ([]*OwnerBonds, error) {
|
||||||
|
ownerBonds := make([]*OwnerBonds, len(ownerAddresses))
|
||||||
|
for index, ownerAddress := range ownerAddresses {
|
||||||
|
bondsObj, err := q.GetBondsByOwner(ctx, ownerAddress)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ownerBonds[index] = bondsObj
|
||||||
|
}
|
||||||
|
|
||||||
|
return ownerBonds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q queryResolver) GetBondsByOwner(ctx context.Context, address string) (*OwnerBonds, error) {
|
||||||
|
bondQueryClient := bondtypes.NewQueryClient(q.ctx)
|
||||||
|
bondResp, err := bondQueryClient.GetBondsByOwner(context.Background(), &bondtypes.QueryGetBondsByOwnerRequest{Owner: address})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ownerBonds := make([]*Bond, len(bondResp.GetBonds()))
|
||||||
|
for i, bond := range bondResp.GetBonds() {
|
||||||
|
bondObj, err := getGQLBond(&bond)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ownerBonds[i] = bondObj
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OwnerBonds{Bonds: ownerBonds, Owner: address}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q queryResolver) GetAuctionsByIds(ctx context.Context, ids []string) ([]*Auction, error) {
|
||||||
|
auctionQueryClient := auctiontypes.NewQueryClient(q.ctx)
|
||||||
|
gqlAuctionResponse := make([]*Auction, len(ids))
|
||||||
|
for i, id := range ids {
|
||||||
|
auctionObj, err := auctionQueryClient.GetAuction(context.Background(), &auctiontypes.AuctionRequest{Id: id})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bidsObj, err := auctionQueryClient.GetBids(context.Background(), &auctiontypes.BidsRequest{AuctionId: id})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gqlAuction, err := GetGQLAuction(auctionObj.GetAuction(), bidsObj.GetBids())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gqlAuctionResponse[i] = gqlAuction
|
||||||
|
}
|
||||||
|
|
||||||
|
return gqlAuctionResponse, nil
|
||||||
|
}
|
44
gql/server.go
Normal file
44
gql/server.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package gql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/99designs/gqlgen/graphql/handler"
|
||||||
|
"github.com/99designs/gqlgen/graphql/playground"
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Server configures and starts the GQL server.
|
||||||
|
func Server(ctx client.Context) {
|
||||||
|
if !viper.GetBool("gql-server") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logFile := viper.GetString("log-file")
|
||||||
|
|
||||||
|
port := viper.GetString("gql-port")
|
||||||
|
|
||||||
|
srv := handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: &Resolver{
|
||||||
|
ctx: ctx,
|
||||||
|
logFile: logFile,
|
||||||
|
}}))
|
||||||
|
|
||||||
|
http.Handle("/", playground.Handler("GraphQL playground", "/api"))
|
||||||
|
|
||||||
|
if viper.GetBool("gql-playground") {
|
||||||
|
apiBase := viper.GetString("gql-playground-api-base")
|
||||||
|
|
||||||
|
http.Handle("/webui", playground.Handler("GraphQL playground", apiBase+"/api"))
|
||||||
|
http.Handle("/console", playground.Handler("GraphQL playground", apiBase+"/graphql"))
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Handle("/api", srv)
|
||||||
|
http.Handle("/graphql", srv)
|
||||||
|
|
||||||
|
log.Info("Connect to GraphQL playground", "url", fmt.Sprintf("http://localhost:%s", port))
|
||||||
|
err := http.ListenAndServe(":"+port, nil)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
99
gql/status.go
Normal file
99
gql/status.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package gql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NodeDataPath is the path to the ethermintd data folder.
|
||||||
|
var NodeDataPath = os.ExpandEnv("$HOME/.ethermintd/data")
|
||||||
|
|
||||||
|
func getStatusInfo(client client.Context) (*NodeInfo, *SyncInfo, *ValidatorInfo, error) {
|
||||||
|
nodeClient, err := client.GetNode()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
nodeStatus, err := nodeClient.Status(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &NodeInfo{
|
||||||
|
ID: string(nodeStatus.NodeInfo.ID()),
|
||||||
|
Network: nodeStatus.NodeInfo.Network,
|
||||||
|
Moniker: nodeStatus.NodeInfo.Moniker,
|
||||||
|
}, &SyncInfo{
|
||||||
|
LatestBlockHash: nodeStatus.SyncInfo.LatestBlockHash.String(),
|
||||||
|
LatestBlockHeight: strconv.FormatInt(nodeStatus.SyncInfo.LatestBlockHeight, 10),
|
||||||
|
LatestBlockTime: nodeStatus.SyncInfo.LatestBlockTime.String(),
|
||||||
|
CatchingUp: nodeStatus.SyncInfo.CatchingUp,
|
||||||
|
}, &ValidatorInfo{
|
||||||
|
Address: nodeStatus.ValidatorInfo.Address.String(),
|
||||||
|
VotingPower: strconv.FormatInt(nodeStatus.ValidatorInfo.VotingPower, 10),
|
||||||
|
ProposerPriority: nil,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNetInfo(client client.Context) (string, []*PeerInfo, error) {
|
||||||
|
nodeClient, err := client.GetNode()
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
netInfo, err := nodeClient.NetInfo(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
peers := netInfo.Peers
|
||||||
|
peersInfo := make([]*PeerInfo, len(peers))
|
||||||
|
for index, peer := range peers {
|
||||||
|
peersInfo[index] = &PeerInfo{
|
||||||
|
Node: &NodeInfo{
|
||||||
|
ID: string(peer.NodeInfo.ID()),
|
||||||
|
Moniker: peer.NodeInfo.Moniker,
|
||||||
|
Network: peer.NodeInfo.Network,
|
||||||
|
},
|
||||||
|
IsOutbound: peer.IsOutbound,
|
||||||
|
RemoteIP: peer.RemoteIP,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strconv.FormatInt(int64(netInfo.NPeers), 10), peersInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getValidatorSet(client client.Context) ([]*ValidatorInfo, error) {
|
||||||
|
nodeClient, err := client.GetNode()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res, err := nodeClient.Validators(context.Background(), nil, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
validatorSet := make([]*ValidatorInfo, len(res.Validators))
|
||||||
|
for index, validator := range res.Validators {
|
||||||
|
proposerPriority := strconv.FormatInt(validator.ProposerPriority, 10)
|
||||||
|
validatorSet[index] = &ValidatorInfo{
|
||||||
|
Address: validator.Address.String(),
|
||||||
|
VotingPower: strconv.FormatInt(validator.VotingPower, 10),
|
||||||
|
ProposerPriority: &proposerPriority,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return validatorSet, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDiskUsage returns disk usage for the given path.
|
||||||
|
func GetDiskUsage(dirPath string) (string, error) {
|
||||||
|
out, err := exec.Command("du", "-sh", dirPath).Output()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Fields(string(out))[0], nil
|
||||||
|
}
|
267
gql/util.go
Normal file
267
gql/util.go
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
package gql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
auctiontypes "github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
bondtypes "github.com/tharsis/ethermint/x/bond/types"
|
||||||
|
nstypes "github.com/tharsis/ethermint/x/nameservice/types"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OwnerAttributeName denotes the owner attribute name for a bond.
|
||||||
|
const OwnerAttributeName = "owner"
|
||||||
|
|
||||||
|
// BondIDAttributeName denotes the record bond ID.
|
||||||
|
const BondIDAttributeName = "bondId"
|
||||||
|
|
||||||
|
// ExpiryTimeAttributeName denotes the record expiry time.
|
||||||
|
const ExpiryTimeAttributeName = "expiryTime"
|
||||||
|
|
||||||
|
func getGQLCoin(coin sdk.Coin) *Coin {
|
||||||
|
gqlCoin := Coin{
|
||||||
|
Type: coin.Denom,
|
||||||
|
Quantity: strconv.FormatInt(coin.Amount.Int64(), 10),
|
||||||
|
}
|
||||||
|
|
||||||
|
return &gqlCoin
|
||||||
|
}
|
||||||
|
|
||||||
|
func getGQLCoins(coins sdk.Coins) []*Coin {
|
||||||
|
gqlCoins := make([]*Coin, len(coins))
|
||||||
|
for index, coin := range coins {
|
||||||
|
gqlCoins[index] = getGQLCoin(coin)
|
||||||
|
}
|
||||||
|
|
||||||
|
return gqlCoins
|
||||||
|
}
|
||||||
|
func GetGQLNameAuthorityRecord(record *nstypes.NameAuthority) (*AuthorityRecord, error) {
|
||||||
|
if record == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &AuthorityRecord{
|
||||||
|
OwnerAddress: record.OwnerAddress,
|
||||||
|
OwnerPublicKey: record.OwnerPublicKey,
|
||||||
|
Height: strconv.FormatUint(record.Height, 10),
|
||||||
|
Status: record.Status,
|
||||||
|
BondID: record.GetBondId(),
|
||||||
|
ExpiryTime: record.GetExpiryTime().String(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getGQLRecord(ctx context.Context, resolver QueryResolver, record nstypes.Record) (*Record, error) {
|
||||||
|
// Nil record.
|
||||||
|
if record.Deleted {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
recordType := record.ToRecordType()
|
||||||
|
attributes, err := getAttributes(&recordType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
references, err := getReferences(ctx, resolver, &recordType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Record{
|
||||||
|
ID: record.Id,
|
||||||
|
BondID: record.GetBondId(),
|
||||||
|
CreateTime: record.GetCreateTime().String(),
|
||||||
|
ExpiryTime: record.GetExpiryTime().String(),
|
||||||
|
Owners: record.GetOwners(),
|
||||||
|
Attributes: attributes,
|
||||||
|
References: references,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getGQLNameRecord(record *nstypes.NameRecord) (*NameRecord, error) {
|
||||||
|
if record == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
records := make([]*NameRecordEntry, len(record.History))
|
||||||
|
for index, entry := range record.History {
|
||||||
|
records[index] = getNameRecordEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &NameRecord{
|
||||||
|
Latest: getNameRecordEntry(record.Latest),
|
||||||
|
History: records,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNameRecordEntry(record *nstypes.NameRecordEntry) *NameRecordEntry {
|
||||||
|
return &NameRecordEntry{
|
||||||
|
ID: record.Id,
|
||||||
|
Height: strconv.FormatUint(record.Height, 10),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getGQLBond(bondObj *bondtypes.Bond) (*Bond, error) {
|
||||||
|
// Nil record.
|
||||||
|
if bondObj == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Bond{
|
||||||
|
ID: bondObj.Id,
|
||||||
|
Owner: bondObj.Owner,
|
||||||
|
Balance: getGQLCoins(bondObj.Balance),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func matchBondOnAttributes(bondObj *bondtypes.Bond, attributes []*KeyValueInput) bool {
|
||||||
|
for _, attr := range attributes {
|
||||||
|
switch attr.Key {
|
||||||
|
case OwnerAttributeName:
|
||||||
|
{
|
||||||
|
if attr.Value.String == nil || bondObj.Owner != *attr.Value.String {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// Only attributes explicitly listed in the switch are queryable.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAuctionBid(bid *auctiontypes.Bid) *AuctionBid {
|
||||||
|
return &AuctionBid{
|
||||||
|
BidderAddress: bid.BidderAddress,
|
||||||
|
Status: bid.Status,
|
||||||
|
CommitHash: bid.CommitHash,
|
||||||
|
CommitTime: bid.GetCommitTime(),
|
||||||
|
RevealTime: bid.GetRevealTime(),
|
||||||
|
CommitFee: getGQLCoin(bid.CommitFee),
|
||||||
|
RevealFee: getGQLCoin(bid.RevealFee),
|
||||||
|
BidAmount: getGQLCoin(bid.BidAmount),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetGQLAuction(auction *auctiontypes.Auction, bids []*auctiontypes.Bid) (*Auction, error) {
|
||||||
|
if auction == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
gqlAuction := Auction{
|
||||||
|
ID: auction.Id,
|
||||||
|
Status: auction.Status,
|
||||||
|
OwnerAddress: auction.OwnerAddress,
|
||||||
|
CreateTime: auction.GetCreateTime(),
|
||||||
|
CommitsEndTime: auction.GetCommitsEndTime(),
|
||||||
|
RevealsEndTime: auction.GetRevealsEndTime(),
|
||||||
|
CommitFee: getGQLCoin(auction.CommitFee),
|
||||||
|
RevealFee: getGQLCoin(auction.RevealFee),
|
||||||
|
MinimumBid: getGQLCoin(auction.MinimumBid),
|
||||||
|
WinnerAddress: auction.WinnerAddress,
|
||||||
|
WinnerBid: getGQLCoin(auction.WinningBid),
|
||||||
|
WinnerPrice: getGQLCoin(auction.WinningPrice),
|
||||||
|
}
|
||||||
|
|
||||||
|
auctionBids := make([]*AuctionBid, len(bids))
|
||||||
|
for index, entry := range bids {
|
||||||
|
auctionBids[index] = getAuctionBid(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
gqlAuction.Bids = auctionBids
|
||||||
|
|
||||||
|
return &gqlAuction, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getReferences(ctx context.Context, resolver QueryResolver, r *nstypes.RecordType) ([]*Record, error) {
|
||||||
|
var ids []string
|
||||||
|
|
||||||
|
for _, value := range r.Attributes {
|
||||||
|
switch value.(type) {
|
||||||
|
case interface{}:
|
||||||
|
if obj, ok := value.(map[string]interface{}); ok {
|
||||||
|
if _, ok := obj["/"]; ok && len(obj) == 1 {
|
||||||
|
if _, ok := obj["/"].(string); ok {
|
||||||
|
ids = append(ids, obj["/"].(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolver.GetRecordsByIds(ctx, ids)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAttributes(r *nstypes.RecordType) ([]*KeyValue, error) {
|
||||||
|
return mapToKeyValuePairs(r.Attributes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapToKeyValuePairs(attrs map[string]interface{}) ([]*KeyValue, error) {
|
||||||
|
var kvPairs []*KeyValue
|
||||||
|
|
||||||
|
trueVal := true
|
||||||
|
falseVal := false
|
||||||
|
|
||||||
|
for key, value := range attrs {
|
||||||
|
kvPair := &KeyValue{
|
||||||
|
Key: key,
|
||||||
|
Value: &Value{},
|
||||||
|
}
|
||||||
|
|
||||||
|
switch val := value.(type) {
|
||||||
|
case nil:
|
||||||
|
kvPair.Value.Null = &trueVal
|
||||||
|
case int:
|
||||||
|
kvPair.Value.Int = &val
|
||||||
|
case float64:
|
||||||
|
kvPair.Value.Float = &val
|
||||||
|
case string:
|
||||||
|
kvPair.Value.String = &val
|
||||||
|
case bool:
|
||||||
|
kvPair.Value.Boolean = &val
|
||||||
|
case interface{}:
|
||||||
|
if obj, ok := value.(map[string]interface{}); ok {
|
||||||
|
if _, ok := obj["/"]; ok && len(obj) == 1 {
|
||||||
|
if _, ok := obj["/"].(string); ok {
|
||||||
|
kvPair.Value.Reference = &Reference{
|
||||||
|
ID: obj["/"].(string),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bytes, err := json.Marshal(obj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonStr := string(bytes)
|
||||||
|
kvPair.Value.JSON = &jsonStr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if kvPair.Value.Null == nil {
|
||||||
|
kvPair.Value.Null = &falseVal
|
||||||
|
}
|
||||||
|
|
||||||
|
valueType := reflect.ValueOf(value)
|
||||||
|
if valueType.Kind() == reflect.Slice {
|
||||||
|
bytes, err := json.Marshal(value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonStr := string(bytes)
|
||||||
|
kvPair.Value.JSON = &jsonStr
|
||||||
|
}
|
||||||
|
|
||||||
|
kvPairs = append(kvPairs, kvPair)
|
||||||
|
}
|
||||||
|
|
||||||
|
return kvPairs, nil
|
||||||
|
}
|
4
gql/version.go
Normal file
4
gql/version.go
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
package gql
|
||||||
|
|
||||||
|
// NameServiceVersion is the registry API version.
|
||||||
|
const NameServiceVersion = "0.3.0"
|
260
gql/vulcanize/dxns/schema.graphql
Normal file
260
gql/vulcanize/dxns/schema.graphql
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
# Reference to another record.
|
||||||
|
type Reference {
|
||||||
|
id: String! # ID of linked record.
|
||||||
|
}
|
||||||
|
|
||||||
|
# Reference to another record.
|
||||||
|
input ReferenceInput {
|
||||||
|
id: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
# Bonds contain funds that are used to pay rent on record registration and renewal.
|
||||||
|
type Bond {
|
||||||
|
id: String! # Primary key, auto-generated by the server.
|
||||||
|
owner: String! # Bond owner cosmos-sdk address.
|
||||||
|
balance: [Coin!] # Current balance for each coin type.
|
||||||
|
}
|
||||||
|
|
||||||
|
# OwnerBonds contains the bonds related the owner
|
||||||
|
type OwnerBonds {
|
||||||
|
owner: String!
|
||||||
|
bonds: [Bond!]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Mutations require payment in coins (e.g. 100wire).
|
||||||
|
# Used by the wallet to get the account balance for display and mutations.
|
||||||
|
type Coin {
|
||||||
|
type: String! # e.g. 'WIRE'
|
||||||
|
quantity: String! # e.g. 1000000
|
||||||
|
}
|
||||||
|
# Represents an account on the blockchain.
|
||||||
|
# Mutations have to be signed by a particular account.
|
||||||
|
type Account {
|
||||||
|
address: String! # Blockchain address.
|
||||||
|
pubKey: String # Public key.
|
||||||
|
number: String! # Account number.
|
||||||
|
sequence: String! # Sequence number used to prevent replays.
|
||||||
|
balance: [Coin!] # Current balance for each coin type.
|
||||||
|
}
|
||||||
|
|
||||||
|
# Value of a given type.
|
||||||
|
type Value {
|
||||||
|
null: Boolean
|
||||||
|
|
||||||
|
int: Int
|
||||||
|
float: Float
|
||||||
|
string: String
|
||||||
|
boolean: Boolean
|
||||||
|
json: String
|
||||||
|
|
||||||
|
reference: Reference
|
||||||
|
|
||||||
|
values: [Value]
|
||||||
|
}
|
||||||
|
# Value of a given type used as input to queries.
|
||||||
|
input ValueInput {
|
||||||
|
null: Boolean
|
||||||
|
|
||||||
|
int: Int
|
||||||
|
float: Float
|
||||||
|
string: String
|
||||||
|
boolean: Boolean
|
||||||
|
|
||||||
|
reference: ReferenceInput
|
||||||
|
|
||||||
|
values: [ValueInput]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Key/value pair.
|
||||||
|
type KeyValue {
|
||||||
|
key: String!
|
||||||
|
value: Value!
|
||||||
|
}
|
||||||
|
|
||||||
|
# Key/value pair for inputs.
|
||||||
|
input KeyValueInput {
|
||||||
|
key: String!
|
||||||
|
value: ValueInput!
|
||||||
|
}
|
||||||
|
|
||||||
|
# Status information about a node (https://docs.tendermint.com/master/rpc/#/Info/status).
|
||||||
|
type NodeInfo {
|
||||||
|
id: String! # Tendermint Node ID.
|
||||||
|
network: String! # Name of the network/blockchain.
|
||||||
|
moniker: String! # Name of the node.
|
||||||
|
}
|
||||||
|
|
||||||
|
# Node sync status.
|
||||||
|
type SyncInfo {
|
||||||
|
latest_block_hash: String!
|
||||||
|
latest_block_height: String!
|
||||||
|
latest_block_time: String!
|
||||||
|
catching_up: Boolean!
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validator set info (https://docs.tendermint.com/master/rpc/#/Info/validators).
|
||||||
|
type ValidatorInfo {
|
||||||
|
address: String!
|
||||||
|
voting_power: String!
|
||||||
|
proposer_priority: String
|
||||||
|
}
|
||||||
|
|
||||||
|
# Network/peer info (https://docs.tendermint.com/master/rpc/#/Info/net_info).
|
||||||
|
type PeerInfo {
|
||||||
|
node: NodeInfo!
|
||||||
|
is_outbound: Boolean!
|
||||||
|
remote_ip: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
# Vulcanize DXNS status.
|
||||||
|
type Status {
|
||||||
|
version: String!
|
||||||
|
node: NodeInfo!
|
||||||
|
sync: SyncInfo!
|
||||||
|
validator: ValidatorInfo
|
||||||
|
validators: [ValidatorInfo]!
|
||||||
|
num_peers: String!
|
||||||
|
peers: [PeerInfo]
|
||||||
|
disk_usage: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# An auction bid.
|
||||||
|
type AuctionBid {
|
||||||
|
bidderAddress: String!
|
||||||
|
status: String!
|
||||||
|
commitHash: String!
|
||||||
|
commitTime: String!
|
||||||
|
commitFee: Coin!
|
||||||
|
revealTime: String!
|
||||||
|
revealFee: Coin!
|
||||||
|
bidAmount: Coin!
|
||||||
|
}
|
||||||
|
|
||||||
|
# A sealed-bid, 2nd price auction.
|
||||||
|
type Auction {
|
||||||
|
id: String! # Auction ID.
|
||||||
|
status: String! # Auction status (commit, reveal, expired).
|
||||||
|
ownerAddress: String! # Auction owner time.
|
||||||
|
createTime: String! # Create time.
|
||||||
|
commitsEndTime: String! # Commit phase end time.
|
||||||
|
revealsEndTime: String! # Reveal phase end time.
|
||||||
|
commitFee: Coin! # Fee required to bid/participate in the auction.
|
||||||
|
revealFee: Coin! # Reveal fee (paid back to bidders only if they unseal/reveal the bid).
|
||||||
|
minimumBid: Coin! # Minimum bid amount.
|
||||||
|
winnerAddress: String! # Winner address.
|
||||||
|
winnerBid: Coin! # The winning bid amount.
|
||||||
|
winnerPrice: Coin! # The price that the winner actually pays (2nd highest bid).
|
||||||
|
bids: [AuctionBid] # Bids make in the auction.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Record defines the basic properties of an entity in the graph database.
|
||||||
|
type Record {
|
||||||
|
id: String! # Computed attribute: Multibase encoded content hash (https://github.com/multiformats/multibase).
|
||||||
|
names: [String!] # Names pointing to this CID (reverse lookup).
|
||||||
|
|
||||||
|
bondId: String! # Associated bond ID.
|
||||||
|
createTime: String! # Record create time.
|
||||||
|
expiryTime: String! # Record expiry time.
|
||||||
|
|
||||||
|
owners: [String!] # Addresses of record owners.
|
||||||
|
attributes: [KeyValue] # Record attributes.
|
||||||
|
references: [Record] # Record references.
|
||||||
|
}
|
||||||
|
|
||||||
|
# Name authority record.
|
||||||
|
type AuthorityRecord {
|
||||||
|
ownerAddress: String! # Owner address.
|
||||||
|
ownerPublicKey: String! # Owner public key.
|
||||||
|
height: String! # Height at which record was created.
|
||||||
|
status: String! # Status (active, auction, expired).
|
||||||
|
bondId: String! # Associated bond ID.
|
||||||
|
expiryTime: String! # Authority expiry time.
|
||||||
|
auction: Auction # Authority auction.
|
||||||
|
}
|
||||||
|
|
||||||
|
# Name record entry, created at a particular height.
|
||||||
|
type NameRecordEntry {
|
||||||
|
id: String! # Target record ID.
|
||||||
|
height: String! # Height at which record was created.
|
||||||
|
}
|
||||||
|
|
||||||
|
# Name record stores the latest and historical name -> record ID mappings.
|
||||||
|
type NameRecord {
|
||||||
|
latest: NameRecordEntry! # Latest mame record entry.
|
||||||
|
history: [NameRecordEntry] # Historical name record entries.
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
#
|
||||||
|
# Status API.
|
||||||
|
#
|
||||||
|
getStatus: Status!
|
||||||
|
|
||||||
|
# Get blockchain accounts.
|
||||||
|
getAccounts(
|
||||||
|
addresses: [String!]
|
||||||
|
): [Account]
|
||||||
|
|
||||||
|
# Get bonds by IDs.
|
||||||
|
getBondsByIds(
|
||||||
|
ids: [String!]
|
||||||
|
): [Bond]
|
||||||
|
|
||||||
|
# Query bonds.
|
||||||
|
queryBonds(
|
||||||
|
attributes: [KeyValueInput]
|
||||||
|
): [Bond]
|
||||||
|
|
||||||
|
# Query bonds by owner.
|
||||||
|
queryBondsByOwner(
|
||||||
|
ownerAddresses: [String!]
|
||||||
|
): [OwnerBonds]
|
||||||
|
|
||||||
|
#
|
||||||
|
# GraphDB API.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Get records by IDs.
|
||||||
|
getRecordsByIds(
|
||||||
|
ids: [String!]
|
||||||
|
): [Record]
|
||||||
|
|
||||||
|
# Query records.
|
||||||
|
queryRecords(
|
||||||
|
# Multiple attribute conditions are in a logical AND.
|
||||||
|
attributes: [KeyValueInput]
|
||||||
|
|
||||||
|
# Whether to query all records, not just named ones (false by default).
|
||||||
|
all: Boolean
|
||||||
|
): [Record]
|
||||||
|
|
||||||
|
#
|
||||||
|
# Naming API.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Lookup authority information.
|
||||||
|
lookupAuthorities(
|
||||||
|
names: [String!]
|
||||||
|
): [AuthorityRecord]!
|
||||||
|
|
||||||
|
# Lookup name to record mapping information.
|
||||||
|
lookupNames(
|
||||||
|
names: [String!]
|
||||||
|
): [NameRecord]!
|
||||||
|
|
||||||
|
# Resolve names to records.
|
||||||
|
resolveNames(
|
||||||
|
names: [String!]
|
||||||
|
): [Record]!
|
||||||
|
|
||||||
|
#
|
||||||
|
# Auctions API.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Get auctions by IDs.
|
||||||
|
getAuctionsByIds(
|
||||||
|
ids: [String!]
|
||||||
|
): [Auction]
|
||||||
|
}
|
15
proto/vulcanize/auction/v1beta1/genesis.proto
Normal file
15
proto/vulcanize/auction/v1beta1/genesis.proto
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package vulcanize.auction.v1beta1;
|
||||||
|
|
||||||
|
import "gogoproto/gogo.proto";
|
||||||
|
import "vulcanize/auction/v1beta1/types.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tharsis/ethermint/x/auction/types";
|
||||||
|
|
||||||
|
// GenesisState defines the genesis state of the auction module
|
||||||
|
message GenesisState {
|
||||||
|
Params params = 1 [(gogoproto.nullable) = false];
|
||||||
|
repeated Auction auctions = 2 [
|
||||||
|
(gogoproto.moretags) = "json:\"bonds\" yaml:\"bonds\""
|
||||||
|
];
|
||||||
|
}
|
149
proto/vulcanize/auction/v1beta1/query.proto
Normal file
149
proto/vulcanize/auction/v1beta1/query.proto
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package vulcanize.auction.v1beta1;
|
||||||
|
|
||||||
|
import "gogoproto/gogo.proto";
|
||||||
|
import "google/api/annotations.proto";
|
||||||
|
import "cosmos/base/query/v1beta1/pagination.proto";
|
||||||
|
import "cosmos/base/v1beta1/coin.proto";
|
||||||
|
import "vulcanize/auction/v1beta1/types.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tharsis/ethermint/x/auction/types";
|
||||||
|
|
||||||
|
// AuctionsRequest is the format for querying all the auctions
|
||||||
|
message AuctionsRequest {
|
||||||
|
// pagination defines an optional pagination info for the next request
|
||||||
|
cosmos.base.query.v1beta1.PageRequest pagination = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuctionsResponse returns the list of all auctions
|
||||||
|
message AuctionsResponse {
|
||||||
|
// List of auctions
|
||||||
|
Auctions auctions = 1;
|
||||||
|
// pagination defines an optional pagination info for the next request
|
||||||
|
cosmos.base.query.v1beta1.PageRequest pagination = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuctionRequest is the format for querying a specific auction
|
||||||
|
message AuctionRequest {
|
||||||
|
// Auction ID
|
||||||
|
string id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuctionResponse returns the details of the queried auction
|
||||||
|
message AuctionResponse {
|
||||||
|
// Auction details
|
||||||
|
Auction auction = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BidRequest is the format for querying a specific bid in an auction
|
||||||
|
message BidRequest {
|
||||||
|
// Auction ID
|
||||||
|
string auction_id = 1;
|
||||||
|
// Bidder address
|
||||||
|
string bidder = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BidResponse returns the details of the queried bid
|
||||||
|
message BidResponse {
|
||||||
|
// Bid details
|
||||||
|
Bid bid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BidsRequest is the format for querying all bids in an auction
|
||||||
|
message BidsRequest {
|
||||||
|
// Auction ID
|
||||||
|
string auction_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BidsResponse returns details of all bids in an auction
|
||||||
|
message BidsResponse {
|
||||||
|
// List of bids in the auction
|
||||||
|
repeated Bid bids = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuctionsByBidderRequest is the format for querying all auctions containing a bidder address
|
||||||
|
message AuctionsByBidderRequest {
|
||||||
|
// Address of the bidder
|
||||||
|
string bidder_address = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuctionsByBidderResponse returns all auctions containing a bidder
|
||||||
|
message AuctionsByBidderResponse {
|
||||||
|
// List of auctions
|
||||||
|
Auctions auctions = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuctionsByOwnerRequest is the format for querying all auctions created by an owner
|
||||||
|
message AuctionsByOwnerRequest {
|
||||||
|
// Address of the owner
|
||||||
|
string owner_address = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuctionsByOwnerResponse returns all auctions created by an owner
|
||||||
|
message AuctionsByOwnerResponse {
|
||||||
|
// List of auctions
|
||||||
|
Auctions auctions = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryParamsRequest is the format to query the parameters of the auction module
|
||||||
|
message QueryParamsRequest {
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryParamsResponse returns parameters of the auction module
|
||||||
|
message QueryParamsResponse {
|
||||||
|
Params params = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BalanceRequest is the format to fetch all balances
|
||||||
|
message BalanceRequest {
|
||||||
|
}
|
||||||
|
|
||||||
|
message BalanceResponse {
|
||||||
|
// Set of all balances within the auction
|
||||||
|
repeated cosmos.base.v1beta1.Coin balance = 1 [
|
||||||
|
(gogoproto.nullable) = false
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query defines the gRPC querier interface for the auction module
|
||||||
|
service Query {
|
||||||
|
// Auctions queries all auctions
|
||||||
|
rpc Auctions(AuctionsRequest) returns (AuctionsResponse) {
|
||||||
|
option (google.api.http).get = "/vulcanize/auction/v1beta1/auctions";
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAuction queries an auction
|
||||||
|
rpc GetAuction(AuctionRequest) returns (AuctionResponse) {
|
||||||
|
option (google.api.http).get = "/vulcanize/auction/v1beta1/auctions/{id}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBid queries an auction bid
|
||||||
|
rpc GetBid(BidRequest) returns (BidResponse) {
|
||||||
|
option (google.api.http).get = "/vulcanize/auction/v1beta1/bids/{auction_id}/{bidder}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBids queries all auction bids
|
||||||
|
rpc GetBids(BidsRequest) returns (BidsResponse) {
|
||||||
|
option (google.api.http).get = "/vulcanize/auction/v1beta1/bids/{auction_id}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuctionsByBidder queries auctions by bidder
|
||||||
|
rpc AuctionsByBidder(AuctionsByBidderRequest) returns (AuctionsByBidderResponse) {
|
||||||
|
option (google.api.http).get = "/vulcanize/auction/v1beta1/by-bidder/{bidder_address}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuctionsByOwner queries auctions by owner
|
||||||
|
rpc AuctionsByOwner(AuctionsByOwnerRequest) returns (AuctionsByOwnerResponse) {
|
||||||
|
option (google.api.http).get = "/vulcanize/auction/v1beta1/by-owner/{owner_address}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryParams implements the params query command
|
||||||
|
rpc QueryParams(QueryParamsRequest) returns (QueryParamsResponse) {
|
||||||
|
option (google.api.http).get = "/vulcanize/auction/v1beta1/params";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Balance queries the auction module account balance
|
||||||
|
rpc Balance(BalanceRequest) returns (BalanceResponse) {
|
||||||
|
option (google.api.http).get = "/vulcanize/auction/v1beta1/balance";
|
||||||
|
}
|
||||||
|
}
|
122
proto/vulcanize/auction/v1beta1/tx.proto
Normal file
122
proto/vulcanize/auction/v1beta1/tx.proto
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package vulcanize.auction.v1beta1;
|
||||||
|
|
||||||
|
import "gogoproto/gogo.proto";
|
||||||
|
import "google/protobuf/duration.proto";
|
||||||
|
import "cosmos/base/v1beta1/coin.proto";
|
||||||
|
import "vulcanize/auction/v1beta1/types.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tharsis/ethermint/x/auction/types";
|
||||||
|
|
||||||
|
// MsgCreateAuction defines a create auction message
|
||||||
|
message MsgCreateAuction {
|
||||||
|
option (gogoproto.goproto_getters) = false;
|
||||||
|
|
||||||
|
// Duration of the commits phase in seconds
|
||||||
|
google.protobuf.Duration commits_duration = 1 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.stdduration) = true,
|
||||||
|
(gogoproto.moretags) = "json:\"commits_duration\" yaml:\"commits_duration\""
|
||||||
|
];
|
||||||
|
// Duration of the reveals phase in seconds
|
||||||
|
google.protobuf.Duration reveals_duration = 2 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.stdduration) = true,
|
||||||
|
(gogoproto.moretags) = "json:\"reveals_duration\" yaml:\"reveals_duration\""
|
||||||
|
];
|
||||||
|
// Commit fees
|
||||||
|
cosmos.base.v1beta1.Coin commit_fee = 3 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"commit_fee\" yaml:\"commit_fee\""
|
||||||
|
];
|
||||||
|
// Reveal fees
|
||||||
|
cosmos.base.v1beta1.Coin reveal_fee = 4 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"reveal_fee\" yaml:\"reveal_fee\""
|
||||||
|
];
|
||||||
|
// Minimum acceptable bid amount
|
||||||
|
cosmos.base.v1beta1.Coin minimum_bid = 5 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"minimum_bid\" yaml:\"minimum_bid\""
|
||||||
|
];
|
||||||
|
// Address of the signer
|
||||||
|
string signer = 6 [
|
||||||
|
(gogoproto.moretags) = "json:\"signer\" yaml:\"signer\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgCreateAuctionResponse returns the details of the created auction
|
||||||
|
message MsgCreateAuctionResponse {
|
||||||
|
option (gogoproto.goproto_getters) = false;
|
||||||
|
// Auction details
|
||||||
|
Auction auction = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"auction\" yaml:\"auction\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitBid defines the message to commit a bid
|
||||||
|
message MsgCommitBid {
|
||||||
|
option (gogoproto.goproto_getters) = false;
|
||||||
|
|
||||||
|
// Auction ID
|
||||||
|
string auction_id = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"auction_id\" yaml:\"auction_id\""
|
||||||
|
];
|
||||||
|
// Commit Hash
|
||||||
|
string commit_hash = 2 [
|
||||||
|
(gogoproto.moretags) = "json:\"commit_hash\" yaml:\"commit_hash\""
|
||||||
|
];
|
||||||
|
// Address of the signer
|
||||||
|
string signer = 3 [
|
||||||
|
(gogoproto.moretags) = "json:\"signer\" yaml:\"signer\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// RevealBid defines the message to reveal a bid
|
||||||
|
message MsgRevealBid {
|
||||||
|
option (gogoproto.goproto_getters) = false;
|
||||||
|
|
||||||
|
// Auction ID
|
||||||
|
string auction_id = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"auction_id\" yaml:\"auction_id\""
|
||||||
|
];
|
||||||
|
// Commit Hash
|
||||||
|
string reveal = 2 [
|
||||||
|
(gogoproto.moretags) = "json:\"reveal\" yaml:\"reveal\""
|
||||||
|
];
|
||||||
|
// Address of the signer
|
||||||
|
string signer = 3 [
|
||||||
|
(gogoproto.moretags) = "json:\"signer\" yaml:\"signer\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgCommitBidResponse returns the state of the auction after the bid creation
|
||||||
|
message MsgCommitBidResponse {
|
||||||
|
option (gogoproto.goproto_getters) = false;
|
||||||
|
// Auction details
|
||||||
|
Bid bid = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"bid\" yaml:\"bid\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgRevealBidResponse returns the state of the auction after the bid reveal
|
||||||
|
message MsgRevealBidResponse {
|
||||||
|
option (gogoproto.goproto_getters) = false;
|
||||||
|
// Auction details
|
||||||
|
Auction auction = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"auction\" yaml:\"auction\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tx defines the gRPC tx interface
|
||||||
|
service Msg {
|
||||||
|
// CreateAuction is the command for creating an auction
|
||||||
|
rpc CreateAuction(MsgCreateAuction) returns (MsgCreateAuctionResponse);
|
||||||
|
|
||||||
|
// CommitBid is the command for committing a bid
|
||||||
|
rpc CommitBid(MsgCommitBid) returns (MsgCommitBidResponse);
|
||||||
|
|
||||||
|
//RevealBid is the command for revealing a bid
|
||||||
|
rpc RevealBid(MsgRevealBid) returns (MsgRevealBidResponse);
|
||||||
|
}
|
||||||
|
|
135
proto/vulcanize/auction/v1beta1/types.proto
Normal file
135
proto/vulcanize/auction/v1beta1/types.proto
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package vulcanize.auction.v1beta1;
|
||||||
|
|
||||||
|
import "gogoproto/gogo.proto";
|
||||||
|
import "google/protobuf/duration.proto";
|
||||||
|
import "google/protobuf/timestamp.proto";
|
||||||
|
import "cosmos/base/v1beta1/coin.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tharsis/ethermint/x/auction/types";
|
||||||
|
|
||||||
|
// Params defines the auction module parameters
|
||||||
|
message Params {
|
||||||
|
option (gogoproto.goproto_stringer) = false;
|
||||||
|
|
||||||
|
// Duration of the commits phase in seconds
|
||||||
|
google.protobuf.Duration commits_duration = 1 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.stdduration) = true,
|
||||||
|
(gogoproto.moretags) = "json:\"commits_duration\" yaml:\"commits_duration\""
|
||||||
|
];
|
||||||
|
// Duration of the reveals phase in seconds
|
||||||
|
google.protobuf.Duration reveals_duration = 2 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.stdduration) = true,
|
||||||
|
(gogoproto.moretags) = "json:\"reveals_duration\" yaml:\"reveals_duration\""
|
||||||
|
];
|
||||||
|
// Commit fees
|
||||||
|
cosmos.base.v1beta1.Coin commit_fee = 3 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"commit_fee\" yaml:\"commit_fee\""
|
||||||
|
];
|
||||||
|
// Reveal fees
|
||||||
|
cosmos.base.v1beta1.Coin reveal_fee = 4 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"reveal_fee\" yaml:\"reveal_fee\""
|
||||||
|
];
|
||||||
|
// Minimum acceptable bid amount
|
||||||
|
cosmos.base.v1beta1.Coin minimum_bid = 5 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"minimum_bid\" yaml:\"minimum_bid\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auction represents a sealed-bid on-chain auction
|
||||||
|
message Auction {
|
||||||
|
option (gogoproto.goproto_getters) = false;
|
||||||
|
|
||||||
|
string id = 1;
|
||||||
|
string status = 2;
|
||||||
|
// Address of the creator of the auction
|
||||||
|
string owner_address = 3;
|
||||||
|
// Timestamp at which the auction was created
|
||||||
|
google.protobuf.Timestamp create_time = 4 [
|
||||||
|
(gogoproto.stdtime) = true,
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"create_time\" yaml:\"create_time\""
|
||||||
|
];
|
||||||
|
// Timestamp at which the commits phase concluded
|
||||||
|
google.protobuf.Timestamp commits_end_time = 5 [
|
||||||
|
(gogoproto.stdtime) = true,
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"commits_end_time\" yaml:\"commits_end_time\""
|
||||||
|
];
|
||||||
|
// Timestamp at which the reveals phase concluded
|
||||||
|
google.protobuf.Timestamp reveals_end_time = 6 [
|
||||||
|
(gogoproto.stdtime) = true,
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"reveals_end_time\" yaml:\"reveals_end_time\""
|
||||||
|
];
|
||||||
|
// Commit and reveal fees must both be paid when committing a bid
|
||||||
|
// Reveal fee is returned only if the bid is revealed
|
||||||
|
cosmos.base.v1beta1.Coin commit_fee = 7 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"commit_fee\" yaml:\"commit_fee\""
|
||||||
|
];
|
||||||
|
cosmos.base.v1beta1.Coin reveal_fee = 8 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"reveal_fee\" yaml:\"reveal_fee\""
|
||||||
|
];
|
||||||
|
// Minimum acceptable bid amount for a valid commit
|
||||||
|
cosmos.base.v1beta1.Coin minimum_bid = 9 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"minimum_bid\" yaml:\"minimum_bid\""
|
||||||
|
];
|
||||||
|
// Address of the winner
|
||||||
|
string winner_address = 10;
|
||||||
|
// Winning bid, i.e., the highest bid
|
||||||
|
cosmos.base.v1beta1.Coin winning_bid = 11 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"winning_bid\" yaml:\"winning_bid\""
|
||||||
|
];
|
||||||
|
// Amount the winner pays, i.e. the second highest auction
|
||||||
|
cosmos.base.v1beta1.Coin winning_price = 12 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"winning_price\" yaml:\"winning_price\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
message Auctions {
|
||||||
|
option (gogoproto.goproto_getters) = false;
|
||||||
|
|
||||||
|
repeated Auction auctions = 1 [(gogoproto.nullable) = false];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bid represents a sealed bid (commit) made during the auction
|
||||||
|
message Bid {
|
||||||
|
option (gogoproto.goproto_getters) = false;
|
||||||
|
|
||||||
|
string auction_id = 1;
|
||||||
|
string bidder_address = 2;
|
||||||
|
string status = 3;
|
||||||
|
string commit_hash = 4;
|
||||||
|
google.protobuf.Timestamp commit_time = 5 [
|
||||||
|
(gogoproto.stdtime) = true,
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"commit_time\" yaml:\"commit_time\""
|
||||||
|
];
|
||||||
|
cosmos.base.v1beta1.Coin commit_fee = 6 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"commit_fee\" yaml:\"commit_fee\""
|
||||||
|
];
|
||||||
|
google.protobuf.Timestamp reveal_time = 7 [
|
||||||
|
(gogoproto.stdtime) = true,
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"reveal_time\" yaml:\"reveal_time\""
|
||||||
|
];
|
||||||
|
cosmos.base.v1beta1.Coin reveal_fee = 8 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"reveal_fee\" yaml:\"reveal_fee\""
|
||||||
|
];
|
||||||
|
cosmos.base.v1beta1.Coin bid_amount = 9 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"bid_amount\" yaml:\"bid_amount\""
|
||||||
|
];;
|
||||||
|
}
|
29
proto/vulcanize/bond/v1beta1/bond.proto
Normal file
29
proto/vulcanize/bond/v1beta1/bond.proto
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package vulcanize.bond.v1beta1;
|
||||||
|
|
||||||
|
option go_package = "github.com/tharsis/ethermint/x/bond/types";
|
||||||
|
|
||||||
|
import "gogoproto/gogo.proto";
|
||||||
|
import "cosmos/base/v1beta1/coin.proto";
|
||||||
|
|
||||||
|
// Params defines the bond module parameters
|
||||||
|
message Params {
|
||||||
|
// max_bond_amount is maximum amount to bond
|
||||||
|
cosmos.base.v1beta1.Coin max_bond_amount = 1 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"max_bond_amount\" yaml:\"max_bond_amount\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bond represents funds deposited by an account for record rent payments.
|
||||||
|
message Bond {
|
||||||
|
// id is unique identifier of the bond
|
||||||
|
string id = 1;
|
||||||
|
// owner of the bond
|
||||||
|
string owner = 2;
|
||||||
|
// balance of the bond
|
||||||
|
repeated cosmos.base.v1beta1.Coin balance = 3 [
|
||||||
|
(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
|
||||||
|
(gogoproto.moretags) = "json:\"balance\" yaml:\"balance\""
|
||||||
|
];
|
||||||
|
}
|
18
proto/vulcanize/bond/v1beta1/genesis.proto
Normal file
18
proto/vulcanize/bond/v1beta1/genesis.proto
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package vulcanize.bond.v1beta1;
|
||||||
|
|
||||||
|
import "gogoproto/gogo.proto";
|
||||||
|
import "vulcanize/bond/v1beta1/bond.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tharsis/ethermint/x/bond/types";
|
||||||
|
|
||||||
|
// GenesisState defines the bond module's genesis state.
|
||||||
|
message GenesisState {
|
||||||
|
// params defines all the parameters of the module.
|
||||||
|
Params params = 1 [(gogoproto.nullable) = false];
|
||||||
|
|
||||||
|
// bonds defines all the bonds
|
||||||
|
repeated Bond bonds = 2 [
|
||||||
|
(gogoproto.moretags) = "json:\"bonds\" yaml:\"bonds\""
|
||||||
|
];
|
||||||
|
}
|
109
proto/vulcanize/bond/v1beta1/query.proto
Normal file
109
proto/vulcanize/bond/v1beta1/query.proto
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package vulcanize.bond.v1beta1;
|
||||||
|
|
||||||
|
import "gogoproto/gogo.proto";
|
||||||
|
import "vulcanize/bond/v1beta1/bond.proto";
|
||||||
|
import "google/api/annotations.proto";
|
||||||
|
import "cosmos/base/query/v1beta1/pagination.proto";
|
||||||
|
import "cosmos/base/v1beta1/coin.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tharsis/ethermint/x/bond/types";
|
||||||
|
|
||||||
|
// Query defines the gRPC querier service for bond module
|
||||||
|
service Query {
|
||||||
|
// Params queries bonds module params.
|
||||||
|
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
|
||||||
|
option (google.api.http).get = "/vulcanize/bond/v1beta1/params";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bonds queries bonds list.
|
||||||
|
rpc Bonds(QueryGetBondsRequest) returns (QueryGetBondsResponse) {
|
||||||
|
option (google.api.http).get = "/vulcanize/bond/v1beta1/bonds";
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBondById
|
||||||
|
rpc GetBondById(QueryGetBondByIdRequest) returns (QueryGetBondByIdResponse){
|
||||||
|
option (google.api.http).get = "/vulcanize/bond/v1beta1/bonds/{id}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Bonds List by Owner
|
||||||
|
rpc GetBondsByOwner(QueryGetBondsByOwnerRequest) returns (QueryGetBondsByOwnerResponse){
|
||||||
|
option (google.api.http).get = "/vulcanize/bond/v1beta1/by-owner/{owner}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Bonds module balance
|
||||||
|
rpc GetBondsModuleBalance(QueryGetBondModuleBalanceRequest) returns (QueryGetBondModuleBalanceResponse){
|
||||||
|
option (google.api.http).get = "/vulcanize/bond/v1beta1/balance";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryParamsRequest is request for query the bond module params
|
||||||
|
message QueryParamsRequest{
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryParamsResponse returns response type of bond module params
|
||||||
|
message QueryParamsResponse{
|
||||||
|
Params params = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"params\" yaml:\"params\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGetBondById queries a bond by bond-id.
|
||||||
|
message QueryGetBondsRequest{
|
||||||
|
// pagination defines an optional pagination for the request.
|
||||||
|
cosmos.base.query.v1beta1.PageRequest pagination = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGetBondsResponse is response type for get the bonds by bond-id
|
||||||
|
message QueryGetBondsResponse{
|
||||||
|
repeated Bond bonds = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"bonds\" yaml:\"bonds\""
|
||||||
|
];
|
||||||
|
// pagination defines the pagination in the response.
|
||||||
|
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGetBondById
|
||||||
|
message QueryGetBondByIdRequest{
|
||||||
|
string id = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"id\" yaml:\"id\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGetBondByIdResponse returns QueryGetBondById query response
|
||||||
|
message QueryGetBondByIdResponse{
|
||||||
|
Bond bond = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"bond\" yaml:\"bond\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGetBondsByOwnerRequest is request type for Query/GetBondsByOwner RPC Method
|
||||||
|
message QueryGetBondsByOwnerRequest{
|
||||||
|
string owner = 1;
|
||||||
|
// pagination defines the pagination in the response.
|
||||||
|
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGetBondsByOwnerResponse is response type for Query/GetBondsByOwner RPC Method
|
||||||
|
message QueryGetBondsByOwnerResponse {
|
||||||
|
repeated Bond bonds = 1 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"bonds\" yaml:\"bonds\""
|
||||||
|
];
|
||||||
|
// pagination defines the pagination in the response.
|
||||||
|
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGetBondModuleBalanceRequest is request type for bond module balance rpc method
|
||||||
|
message QueryGetBondModuleBalanceRequest{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGetBondModuleBalanceResponse is the response type for bond module balance rpc method
|
||||||
|
message QueryGetBondModuleBalanceResponse{
|
||||||
|
repeated cosmos.base.v1beta1.Coin balance = 2 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
|
||||||
|
(gogoproto.moretags) = "json:\"coins\" yaml:\"coins\""
|
||||||
|
];
|
||||||
|
}
|
77
proto/vulcanize/bond/v1beta1/tx.proto
Normal file
77
proto/vulcanize/bond/v1beta1/tx.proto
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package vulcanize.bond.v1beta1;
|
||||||
|
|
||||||
|
option go_package = "github.com/tharsis/ethermint/x/bond/types";
|
||||||
|
|
||||||
|
import "gogoproto/gogo.proto";
|
||||||
|
import "cosmos/base/v1beta1/coin.proto";
|
||||||
|
|
||||||
|
// Msg defines the bond Msg service.
|
||||||
|
service Msg {
|
||||||
|
// CreateBond defines a method for creating a new bond.
|
||||||
|
rpc CreateBond(MsgCreateBond) returns (MsgCreateBondResponse);
|
||||||
|
|
||||||
|
// RefillBond defines a method for refilling amount for bond.
|
||||||
|
rpc RefillBond(MsgRefillBond) returns (MsgRefillBondResponse);
|
||||||
|
|
||||||
|
// WithdrawBond defines a method for withdrawing amount from bond.
|
||||||
|
rpc WithdrawBond(MsgWithdrawBond) returns (MsgWithdrawBondResponse);
|
||||||
|
|
||||||
|
// CancelBond defines a method for cancelling a bond.
|
||||||
|
rpc CancelBond(MsgCancelBond) returns (MsgCancelBondResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgCreateBond defines a SDK message for creating a new bond.
|
||||||
|
message MsgCreateBond{
|
||||||
|
string signer = 1;
|
||||||
|
repeated cosmos.base.v1beta1.Coin coins = 2 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
|
||||||
|
(gogoproto.moretags) = "json:\"coins\" yaml:\"coins\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgCreateBondResponse defines the Msg/CreateBond response type.
|
||||||
|
message MsgCreateBondResponse{
|
||||||
|
string id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgRefillBond defines a SDK message for refill the amount for bond.
|
||||||
|
message MsgRefillBond{
|
||||||
|
string id = 1;
|
||||||
|
string signer = 2;
|
||||||
|
repeated cosmos.base.v1beta1.Coin coins = 3 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
|
||||||
|
(gogoproto.moretags) = "json:\"coins\" yaml:\"coins\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgRefillBondResponse defines the Msg/RefillBond response type.
|
||||||
|
message MsgRefillBondResponse{
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgWithdrawBond defines a SDK message for withdrawing amount from bond.
|
||||||
|
message MsgWithdrawBond {
|
||||||
|
string id = 1;
|
||||||
|
string signer = 2;
|
||||||
|
repeated cosmos.base.v1beta1.Coin coins = 3 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
|
||||||
|
(gogoproto.moretags) = "json:\"coins\" yaml:\"coins\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgWithdrawBondResponse defines the Msg/WithdrawBond response type.
|
||||||
|
message MsgWithdrawBondResponse{
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgCancelBond defines a SDK message for the cancel the bond.
|
||||||
|
message MsgCancelBond{
|
||||||
|
string id = 1;
|
||||||
|
string signer = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgCancelBondResponse defines the Msg/CancelBond response type.
|
||||||
|
message MsgCancelBondResponse{
|
||||||
|
}
|
30
proto/vulcanize/nameservice/v1beta1/genesis.proto
Normal file
30
proto/vulcanize/nameservice/v1beta1/genesis.proto
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package vulcanize.nameservice.v1beta1;
|
||||||
|
|
||||||
|
import "gogoproto/gogo.proto";
|
||||||
|
import "vulcanize/nameservice/v1beta1/nameservice.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tharsis/ethermint/x/nameservice/types";
|
||||||
|
|
||||||
|
// GenesisState defines the nameservice module's genesis state.
|
||||||
|
message GenesisState {
|
||||||
|
// params defines all the params of nameservice module.
|
||||||
|
Params params = 1 [
|
||||||
|
(gogoproto.nullable) = false
|
||||||
|
];
|
||||||
|
// records
|
||||||
|
repeated Record records = 2 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"records\" yaml:\"records\""
|
||||||
|
];
|
||||||
|
// authorities
|
||||||
|
repeated AuthorityEntry authorities = 3 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"authorities\" yaml:\"authorities\""
|
||||||
|
];
|
||||||
|
// names
|
||||||
|
repeated NameEntry names = 4 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"names\" yaml:\"names\""
|
||||||
|
];
|
||||||
|
}
|
170
proto/vulcanize/nameservice/v1beta1/nameservice.proto
Normal file
170
proto/vulcanize/nameservice/v1beta1/nameservice.proto
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package vulcanize.nameservice.v1beta1;
|
||||||
|
|
||||||
|
import "google/protobuf/duration.proto";
|
||||||
|
import "google/protobuf/timestamp.proto";
|
||||||
|
import "gogoproto/gogo.proto";
|
||||||
|
import "cosmos/base/v1beta1/coin.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tharsis/ethermint/x/nameservice/types";
|
||||||
|
|
||||||
|
// Params defines the nameservice module parameters
|
||||||
|
message Params {
|
||||||
|
cosmos.base.v1beta1.Coin record_rent = 1 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"record_rent\" yaml:\"record_rent\""
|
||||||
|
];
|
||||||
|
google.protobuf.Duration record_rent_duration = 2 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.stdduration) = true,
|
||||||
|
(gogoproto.moretags) = "json:\"record_rent_duration\" yaml:\"record_rent_duration\""
|
||||||
|
];
|
||||||
|
cosmos.base.v1beta1.Coin authority_rent = 3 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"authority_rent\" yaml:\"authority_rent\""
|
||||||
|
];
|
||||||
|
google.protobuf.Duration authority_rent_duration = 4 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.stdduration) = true,
|
||||||
|
(gogoproto.moretags) = "json:\"authority_rent_duration\" yaml:\"authority_rent_duration\""
|
||||||
|
];
|
||||||
|
google.protobuf.Duration authority_grace_period = 5 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.stdduration) = true,
|
||||||
|
(gogoproto.moretags) = "json:\"authority_grace_period\" yaml:\"authority_grace_period\""
|
||||||
|
];
|
||||||
|
bool authority_auction_enabled = 6 [
|
||||||
|
(gogoproto.moretags) = "json:\"authority_auction_enabled\" yaml:\"authority_auction_enabled\""
|
||||||
|
];
|
||||||
|
google.protobuf.Duration authority_auction_commits_duration = 7 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.stdduration) = true,
|
||||||
|
(gogoproto.moretags) = "json:\"authority_auction_commits_duration\" yaml:\"authority_auction_commits_duration\""
|
||||||
|
];
|
||||||
|
google.protobuf.Duration authority_auction_reveals_duration = 8 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.stdduration) = true,
|
||||||
|
(gogoproto.moretags) = "json:\"authority_auction_reveals_duration\" yaml:\"authority_auction_reveals_duration\""
|
||||||
|
];
|
||||||
|
cosmos.base.v1beta1.Coin authority_auction_commit_fee = 9 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"authority_auction_commit_fee\" yaml:\"authority_auction_commit_fee\""
|
||||||
|
];
|
||||||
|
cosmos.base.v1beta1.Coin authority_auction_reveal_fee = 10 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"authority_auction_reveal_fee\" yaml:\"authority_auction_reveal_fee\""
|
||||||
|
];
|
||||||
|
cosmos.base.v1beta1.Coin authority_auction_minimum_bid = 11 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"authority_auction_minimum_bid\" yaml:\"authority_auction_minimum_bid\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Params defines the nameservice module records
|
||||||
|
message Record {
|
||||||
|
string id = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"id\" yaml:\"id\""
|
||||||
|
];
|
||||||
|
string bond_id = 2 [
|
||||||
|
(gogoproto.moretags) = "json:\"bondId\" yaml:\"bondId\""
|
||||||
|
];
|
||||||
|
google.protobuf.Timestamp create_time = 3 [
|
||||||
|
(gogoproto.stdtime) = true,
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"createTime\" yaml:\"createTime\""
|
||||||
|
];
|
||||||
|
google.protobuf.Timestamp expiry_time = 4 [
|
||||||
|
(gogoproto.stdtime) = true,
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"expiryTime\" yaml:\"expiryTime\""
|
||||||
|
];
|
||||||
|
bool deleted = 5;
|
||||||
|
repeated string owners = 6 [
|
||||||
|
(gogoproto.moretags) = "json:\"owners\" yaml:\"owners\""
|
||||||
|
];
|
||||||
|
bytes attributes = 7 [
|
||||||
|
(gogoproto.moretags) = "json:\"attributes\" yaml:\"attributes\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuthorityEntry defines the nameservice module AuthorityEntries
|
||||||
|
message AuthorityEntry{
|
||||||
|
string name = 1;
|
||||||
|
NameAuthority entry = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NameAuthority
|
||||||
|
message NameAuthority {
|
||||||
|
// Owner public key.
|
||||||
|
string owner_public_key = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"ownerPublicKey\" yaml:\"ownerPublicKey\""
|
||||||
|
];
|
||||||
|
// Owner address.
|
||||||
|
string owner_address = 2 [
|
||||||
|
(gogoproto.moretags) = "json:\"ownerAddress\" yaml:\"ownerAddress\""
|
||||||
|
];
|
||||||
|
// height at which name/authority was created.
|
||||||
|
uint64 height = 3;
|
||||||
|
string status = 4;
|
||||||
|
string auction_id = 5 [
|
||||||
|
(gogoproto.moretags) = "json:\"auctionID\" yaml:\"auctionID\""
|
||||||
|
];
|
||||||
|
string bond_id = 6 [
|
||||||
|
(gogoproto.moretags) = "json:\"bondID\" yaml:\"bondID\""
|
||||||
|
];
|
||||||
|
google.protobuf.Timestamp expiry_time = 7 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.stdtime) = true,
|
||||||
|
(gogoproto.moretags) = "json:\"expiryTime\" yaml:\"expiryTime\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// NameEntry
|
||||||
|
message NameEntry{
|
||||||
|
string name = 1;
|
||||||
|
NameRecord entry = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NameRecord
|
||||||
|
message NameRecord {
|
||||||
|
NameRecordEntry latest = 1;
|
||||||
|
repeated NameRecordEntry history = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NameRecordEntry
|
||||||
|
message NameRecordEntry{
|
||||||
|
string id = 1;
|
||||||
|
uint64 height = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signature
|
||||||
|
message Signature{
|
||||||
|
string sig = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"sig\" yaml:\"sig\""
|
||||||
|
];
|
||||||
|
string pub_key = 2 [
|
||||||
|
(gogoproto.moretags) = "json:\"pubKey\" yaml:\"pubKey\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockChangeSet
|
||||||
|
message BlockChangeSet{
|
||||||
|
int64 height = 1;
|
||||||
|
repeated string records = 2;
|
||||||
|
repeated string auctions = 3;
|
||||||
|
repeated AuctionBidInfo auction_bids = 4 [
|
||||||
|
(gogoproto.moretags) = "json:\"auctionBids\" yaml:\"auctionBids\""
|
||||||
|
];
|
||||||
|
repeated string authorities = 5;
|
||||||
|
repeated string names = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuctionBidInfo
|
||||||
|
message AuctionBidInfo {
|
||||||
|
string auction_id = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"auctionID\" yaml:\"auctionID\""
|
||||||
|
];
|
||||||
|
string bidder_address = 2 [
|
||||||
|
(gogoproto.moretags) = "json:\"bidderAddress\" yaml:\"bidderAddress\""
|
||||||
|
];
|
||||||
|
}
|
211
proto/vulcanize/nameservice/v1beta1/query.proto
Normal file
211
proto/vulcanize/nameservice/v1beta1/query.proto
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package vulcanize.nameservice.v1beta1;
|
||||||
|
|
||||||
|
import "vulcanize/nameservice/v1beta1/nameservice.proto";
|
||||||
|
import "google/api/annotations.proto";
|
||||||
|
import "cosmos/base/query/v1beta1/pagination.proto";
|
||||||
|
import "gogoproto/gogo.proto";
|
||||||
|
import "cosmos/base/v1beta1/coin.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tharsis/ethermint/x/nameservice/types";
|
||||||
|
|
||||||
|
// Query defines the gRPC querier service for nameservice module
|
||||||
|
service Query {
|
||||||
|
// Params queries the nameservice module params.
|
||||||
|
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
|
||||||
|
option (google.api.http).get = "/vulcanize/nameservice/v1beta1/params";
|
||||||
|
}
|
||||||
|
// List records
|
||||||
|
rpc ListRecords(QueryListRecordsRequest) returns (QueryListRecordsResponse){
|
||||||
|
option (google.api.http).get = "/vulcanize/nameservice/v1beta1/records";
|
||||||
|
}
|
||||||
|
// Get record by id
|
||||||
|
rpc GetRecord(QueryRecordByIdRequest) returns (QueryRecordByIdResponse){
|
||||||
|
option (google.api.http).get = "/vulcanize/nameservice/v1beta1/records/{id}";
|
||||||
|
}
|
||||||
|
// Get records by bond id
|
||||||
|
rpc GetRecordByBondId(QueryRecordByBondIdRequest) returns (QueryRecordByBondIdResponse){
|
||||||
|
option (google.api.http).get = "/vulcanize/nameservice/v1beta1/records-by-bond-id/{id}";
|
||||||
|
}
|
||||||
|
// Get nameservice module balance
|
||||||
|
rpc GetNameServiceModuleBalance(GetNameServiceModuleBalanceRequest) returns (GetNameServiceModuleBalanceResponse){
|
||||||
|
option (google.api.http).get = "/vulcanize/nameservice/v1beta1/balance";
|
||||||
|
}
|
||||||
|
// List name records
|
||||||
|
rpc ListNameRecords(QueryListNameRecordsRequest) returns (QueryListNameRecordsResponse){
|
||||||
|
option (google.api.http).get = "/vulcanize/nameservice/v1beta1/names";
|
||||||
|
}
|
||||||
|
// Whois method retrieve the name authority info
|
||||||
|
rpc Whois(QueryWhoisRequest) returns (QueryWhoisResponse){
|
||||||
|
option (google.api.http).get = "/vulcanize/nameservice/v1beta1/whois/{name}";
|
||||||
|
}
|
||||||
|
// LookupWrn
|
||||||
|
rpc LookupWrn(QueryLookupWrn) returns (QueryLookupWrnResponse){
|
||||||
|
option (google.api.http).get = "/vulcanize/nameservice/v1beta1/lookup";
|
||||||
|
}
|
||||||
|
// ResolveWrn
|
||||||
|
rpc ResolveWrn(QueryResolveWrn) returns (QueryResolveWrnResponse){
|
||||||
|
option (google.api.http).get = "/vulcanize/nameservice/v1beta1/resolve";
|
||||||
|
}
|
||||||
|
// GetRecordExpiryQueue
|
||||||
|
rpc GetRecordExpiryQueue(QueryGetRecordExpiryQueue) returns (QueryGetRecordExpiryQueueResponse){
|
||||||
|
option (google.api.http).get = "/vulcanize/nameservice/v1beta1/record-expiry";
|
||||||
|
}
|
||||||
|
// GetAuthorityExpiryQueue
|
||||||
|
rpc GetAuthorityExpiryQueue(QueryGetAuthorityExpiryQueue) returns (QueryGetAuthorityExpiryQueueResponse){
|
||||||
|
option (google.api.http).get = "/vulcanize/nameservice/v1beta1/authority-expiry";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryParamsRequest is request type for nameservice params
|
||||||
|
message QueryParamsRequest{
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryParamsResponse is response type for nameservice params
|
||||||
|
message QueryParamsResponse{
|
||||||
|
Params params = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryListRecordsRequest is request type for nameservice records list
|
||||||
|
message QueryListRecordsRequest{
|
||||||
|
// pagination defines an optional pagination for the request.
|
||||||
|
cosmos.base.query.v1beta1.PageRequest pagination = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryListRecordsResponse is response type for nameservice records list
|
||||||
|
message QueryListRecordsResponse{
|
||||||
|
repeated Record records = 1 [
|
||||||
|
(gogoproto.nullable) = false
|
||||||
|
];
|
||||||
|
// pagination defines the pagination in the response.
|
||||||
|
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//QueryRecordByIdRequest is request type for nameservice records by id
|
||||||
|
message QueryRecordByIdRequest{
|
||||||
|
string id = 1 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryRecordByIdResponse is response type for nameservice records by id
|
||||||
|
message QueryRecordByIdResponse{
|
||||||
|
Record record = 1[
|
||||||
|
(gogoproto.nullable) = false
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryRecordByBondIdRequest is request type for get the records by bond-id
|
||||||
|
message QueryRecordByBondIdRequest{
|
||||||
|
string id = 1;
|
||||||
|
// pagination defines an optional pagination for the request.
|
||||||
|
cosmos.base.query.v1beta1.PageRequest pagination = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryRecordByBondIdResponse is response type for records list by bond-id
|
||||||
|
message QueryRecordByBondIdResponse{
|
||||||
|
repeated Record records = 1 [
|
||||||
|
(gogoproto.nullable) = false
|
||||||
|
];
|
||||||
|
// pagination defines the pagination in the response.
|
||||||
|
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNameServiceModuleBalanceRequest is request type for nameservice module accounts balance
|
||||||
|
message GetNameServiceModuleBalanceRequest{
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNameServiceModuleBalanceResponse is response type for nameservice module accounts balance
|
||||||
|
message GetNameServiceModuleBalanceResponse{
|
||||||
|
repeated AccountBalance balances = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccountBalance is nameservice module account balance
|
||||||
|
message AccountBalance {
|
||||||
|
string account_name = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"accountName\" yaml:\"accountName\""
|
||||||
|
];
|
||||||
|
repeated cosmos.base.v1beta1.Coin balance = 3 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
|
||||||
|
(gogoproto.moretags) = "json:\"balance\" yaml:\"balance\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryListNameRecordsRequest is request type for nameservice names records
|
||||||
|
message QueryListNameRecordsRequest{
|
||||||
|
// pagination defines an optional pagination for the request.
|
||||||
|
cosmos.base.query.v1beta1.PageRequest pagination = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryListNameRecordsResponse is response type for nameservice names records
|
||||||
|
message QueryListNameRecordsResponse{
|
||||||
|
repeated NameEntry names = 1 [
|
||||||
|
(gogoproto.nullable) = false
|
||||||
|
];
|
||||||
|
// pagination defines the pagination in the response.
|
||||||
|
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryWhoisRequest is request type for Get NameAuthority
|
||||||
|
message QueryWhoisRequest{
|
||||||
|
string name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryWhoisResponse is response type for whois request
|
||||||
|
message QueryWhoisResponse{
|
||||||
|
NameAuthority name_authority = 1 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"nameAuthority\" yaml:\"nameAuthority\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryLookupWrn is request type for LookupWrn
|
||||||
|
message QueryLookupWrn{
|
||||||
|
string wrn = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryLookupWrnResponse is response type for QueryLookupWrn
|
||||||
|
message QueryLookupWrnResponse{
|
||||||
|
NameRecord name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryResolveWrn is request type for ResolveWrn
|
||||||
|
message QueryResolveWrn{
|
||||||
|
string wrn = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryResolveWrnResponse is response type for QueryResolveWrn
|
||||||
|
message QueryResolveWrnResponse{
|
||||||
|
Record record = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGetRecordExpiryQueue
|
||||||
|
message QueryGetRecordExpiryQueue{
|
||||||
|
// pagination defines an optional pagination for the request.
|
||||||
|
cosmos.base.query.v1beta1.PageRequest pagination = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGetRecordExpiryQueueResponse
|
||||||
|
message QueryGetRecordExpiryQueueResponse{
|
||||||
|
repeated ExpiryQueueRecord records = 1;
|
||||||
|
// pagination defines the pagination in the response.
|
||||||
|
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpiryQueueRecord
|
||||||
|
message ExpiryQueueRecord{
|
||||||
|
string id = 1;
|
||||||
|
repeated string value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGetAuthorityExpiryQueue
|
||||||
|
message QueryGetAuthorityExpiryQueue{
|
||||||
|
// pagination defines an optional pagination for the request.
|
||||||
|
cosmos.base.query.v1beta1.PageRequest pagination = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGetAuthorityExpiryQueueResponse
|
||||||
|
message QueryGetAuthorityExpiryQueueResponse{
|
||||||
|
repeated ExpiryQueueRecord authorities = 1;
|
||||||
|
// pagination defines the pagination in the response.
|
||||||
|
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||||
|
}
|
167
proto/vulcanize/nameservice/v1beta1/tx.proto
Normal file
167
proto/vulcanize/nameservice/v1beta1/tx.proto
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package vulcanize.nameservice.v1beta1;
|
||||||
|
|
||||||
|
import "gogoproto/gogo.proto";
|
||||||
|
import "vulcanize/nameservice/v1beta1/nameservice.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tharsis/ethermint/x/nameservice/types";
|
||||||
|
|
||||||
|
// Msg
|
||||||
|
service Msg {
|
||||||
|
// SetRecord will records a new record with given payload and bond id
|
||||||
|
rpc SetRecord(MsgSetRecord) returns(MsgSetRecordResponse){}
|
||||||
|
// Renew Record will renew the expire record
|
||||||
|
rpc RenewRecord(MsgRenewRecord) returns (MsgRenewRecordResponse){}
|
||||||
|
// AssociateBond
|
||||||
|
rpc AssociateBond(MsgAssociateBond) returns (MsgAssociateBondResponse){}
|
||||||
|
// DissociateBond
|
||||||
|
rpc DissociateBond(MsgDissociateBond) returns (MsgDissociateBondResponse){}
|
||||||
|
// DissociateRecords
|
||||||
|
rpc DissociateRecords(MsgDissociateRecords) returns (MsgDissociateRecordsResponse){}
|
||||||
|
// ReAssociateRecords
|
||||||
|
rpc ReAssociateRecords(MsgReAssociateRecords) returns (MsgReAssociateRecordsResponse){}
|
||||||
|
// SetName will store the name with given wrn and name
|
||||||
|
rpc SetName(MsgSetName) returns (MsgSetNameResponse){}
|
||||||
|
// Reserve name
|
||||||
|
rpc ReserveName(MsgReserveAuthority) returns (MsgReserveAuthorityResponse){}
|
||||||
|
// Delete Name method will remove authority name
|
||||||
|
rpc DeleteName(MsgDeleteNameAuthority) returns (MsgDeleteNameAuthorityResponse){}
|
||||||
|
// SetAuthorityBond
|
||||||
|
rpc SetAuthorityBond(MsgSetAuthorityBond) returns (MsgSetAuthorityBondResponse){}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgSetRecord
|
||||||
|
message MsgSetRecord{
|
||||||
|
string bond_id = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"bondId\" yaml:\"bondId\""
|
||||||
|
];
|
||||||
|
string signer = 2;
|
||||||
|
Payload payload = 3 [
|
||||||
|
(gogoproto.nullable) = false
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgSetRecordResponse
|
||||||
|
message MsgSetRecordResponse{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Payload
|
||||||
|
message Payload {
|
||||||
|
Record record = 1;
|
||||||
|
repeated Signature signatures = 2 [
|
||||||
|
(gogoproto.nullable) = false,
|
||||||
|
(gogoproto.moretags) = "json:\"signatures\" yaml:\"signatures\""
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgSetName
|
||||||
|
message MsgSetName{
|
||||||
|
string wrn = 1;
|
||||||
|
string cid = 2;
|
||||||
|
string signer = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgSetNameResponse
|
||||||
|
message MsgSetNameResponse{
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgReserveName
|
||||||
|
message MsgReserveAuthority{
|
||||||
|
string name = 1;
|
||||||
|
string signer = 2;
|
||||||
|
// if creating a sub-authority.
|
||||||
|
string owner = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgReserveNameResponse
|
||||||
|
message MsgReserveAuthorityResponse{
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgSetAuthorityBond is SDK message for SetAuthorityBond
|
||||||
|
message MsgSetAuthorityBond{
|
||||||
|
string name = 1;
|
||||||
|
string bond_id = 2 [
|
||||||
|
(gogoproto.moretags) = "json:\"bondId\" yaml:\"bondId\""
|
||||||
|
];
|
||||||
|
string signer = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgSetAuthorityBondResponse
|
||||||
|
message MsgSetAuthorityBondResponse{
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgDeleteNameAuthority is SDK message for DeleteNameAuthority
|
||||||
|
message MsgDeleteNameAuthority{
|
||||||
|
string wrn = 1;
|
||||||
|
string signer = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgDeleteNameAuthorityResponse
|
||||||
|
message MsgDeleteNameAuthorityResponse{
|
||||||
|
}
|
||||||
|
|
||||||
|
//MsgRenewRecord is SDK message for Renew a record
|
||||||
|
message MsgRenewRecord{
|
||||||
|
string record_id = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"recordId\" yaml:\"recordId\""
|
||||||
|
];
|
||||||
|
string signer = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgRenewRecordResponse
|
||||||
|
message MsgRenewRecordResponse{
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgAssociateBond
|
||||||
|
message MsgAssociateBond{
|
||||||
|
string record_id = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"recordId\" yaml:\"recordId\""
|
||||||
|
];
|
||||||
|
string bond_id = 2 [
|
||||||
|
(gogoproto.moretags) = "json:\"bondId\" yaml:\"bondId\""
|
||||||
|
];
|
||||||
|
string signer = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgAssociateBondResponse
|
||||||
|
message MsgAssociateBondResponse{
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgDissociateBond is SDK message for Msg/DissociateBond
|
||||||
|
message MsgDissociateBond{
|
||||||
|
string record_id = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"recordId\" yaml:\"recordId\""
|
||||||
|
];
|
||||||
|
string signer = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgDissociateBondResponse is response type for MsgDissociateBond
|
||||||
|
message MsgDissociateBondResponse{
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgDissociateRecords is SDK message for Msg/DissociateRecords
|
||||||
|
message MsgDissociateRecords{
|
||||||
|
string bond_id = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"bondId\" yaml:\"bondId\""
|
||||||
|
];
|
||||||
|
string signer = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgDissociateRecordsResponse is response type for MsgDissociateRecords
|
||||||
|
message MsgDissociateRecordsResponse{
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgReAssociateRecords is SDK message for Msg/ReAssociateRecords
|
||||||
|
message MsgReAssociateRecords{
|
||||||
|
string new_bond_id = 1 [
|
||||||
|
(gogoproto.moretags) = "json:\"newBondId\" yaml:\"newBondId\""
|
||||||
|
];
|
||||||
|
string old_bond_id = 2 [
|
||||||
|
(gogoproto.moretags) = "json:\"oldBondId\" yaml:\"oldBondId\""
|
||||||
|
];
|
||||||
|
string signer = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgReAssociateRecordsResponse is response type for MsgReAssociateRecords
|
||||||
|
message MsgReAssociateRecordsResponse{
|
||||||
|
}
|
@ -63,7 +63,7 @@ fi
|
|||||||
|
|
||||||
# Compile ethermint
|
# Compile ethermint
|
||||||
echo "compiling ethermint"
|
echo "compiling ethermint"
|
||||||
make build-ethermint
|
make build
|
||||||
|
|
||||||
# PID array declaration
|
# PID array declaration
|
||||||
arr=()
|
arr=()
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
tmcli "github.com/tendermint/tendermint/libs/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Tendermint full-node start flags
|
// Tendermint full-node start flags
|
||||||
@ -48,6 +49,8 @@ func AddTxFlags(cmd *cobra.Command) *cobra.Command {
|
|||||||
cmd.PersistentFlags().Float64(flags.FlagGasAdjustment, flags.DefaultGasAdjustment, "adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored ")
|
cmd.PersistentFlags().Float64(flags.FlagGasAdjustment, flags.DefaultGasAdjustment, "adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored ")
|
||||||
cmd.PersistentFlags().StringP(flags.FlagBroadcastMode, "b", flags.BroadcastSync, "Transaction broadcasting mode (sync|async|block)")
|
cmd.PersistentFlags().StringP(flags.FlagBroadcastMode, "b", flags.BroadcastSync, "Transaction broadcasting mode (sync|async|block)")
|
||||||
cmd.PersistentFlags().String(flags.FlagKeyringBackend, keyring.BackendOS, "Select keyring's backend")
|
cmd.PersistentFlags().String(flags.FlagKeyringBackend, keyring.BackendOS, "Select keyring's backend")
|
||||||
|
cmd.PersistentFlags().BoolP(flags.FlagSkipConfirmation, "y", false, "Skip tx broadcasting prompt confirmation")
|
||||||
|
cmd.Flags().StringP(tmcli.OutputFlag, "o", "text", "Output format (text|json)")
|
||||||
|
|
||||||
// --gas can accept integers and "simulate"
|
// --gas can accept integers and "simulate"
|
||||||
// cmd.PersistentFlags().Var(&flags.GasFlagVar, "gas", fmt.Sprintf(
|
// cmd.PersistentFlags().Var(&flags.GasFlagVar, "gas", fmt.Sprintf(
|
||||||
@ -66,3 +69,15 @@ func AddTxFlags(cmd *cobra.Command) *cobra.Command {
|
|||||||
cmd.MarkFlagRequired(flags.FlagChainID)
|
cmd.MarkFlagRequired(flags.FlagChainID)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddGQLFlags adds gql flags for
|
||||||
|
func AddGQLFlags(cmd *cobra.Command) *cobra.Command {
|
||||||
|
// Add flags for GQL server.
|
||||||
|
cmd.PersistentFlags().Bool("gql-server", false, "Start GQL server.")
|
||||||
|
cmd.PersistentFlags().Bool("gql-playground", false, "Enable GQL playground.")
|
||||||
|
cmd.PersistentFlags().String("gql-playground-api-base", "", "GQL API base path to use in GQL playground.")
|
||||||
|
cmd.PersistentFlags().String("gql-port", "9473", "Port to use for the GQL server.")
|
||||||
|
cmd.PersistentFlags().String("log-file", "", "File to tail for GQL 'getLogs' API.")
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@ package server
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/tharsis/ethermint/gql"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@ -400,6 +401,9 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start the GQL Server
|
||||||
|
go gql.Server(clientCtx)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if tmNode.IsRunning() {
|
if tmNode.IsRunning() {
|
||||||
_ = tmNode.Stop()
|
_ = tmNode.Stop()
|
||||||
|
7
testnet/README.md
Normal file
7
testnet/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Testnet
|
||||||
|
|
||||||
|
## Setup local ethermint multi node testnet
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ bash multinode_testnet.sh
|
||||||
|
```
|
201
testnet/full-node.md
Normal file
201
testnet/full-node.md
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
# Instructions to Run Full Node
|
||||||
|
|
||||||
|
Hardware
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Supported
|
||||||
|
|
||||||
|
- **Operating System (OS):** Ubuntu 20.04
|
||||||
|
- **CPU:** 1 core
|
||||||
|
- **RAM:** 2GB
|
||||||
|
- **Storage:** 25GB SSD
|
||||||
|
|
||||||
|
#### Recommended
|
||||||
|
|
||||||
|
- **Operating System (OS):** Ubuntu 20.04
|
||||||
|
- **CPU:** 2 core
|
||||||
|
- **RAM:** 4GB
|
||||||
|
- **Storage:** 50GB SSD
|
||||||
|
|
||||||
|
# A) Setup
|
||||||
|
|
||||||
|
## 1) Install Golang (go)
|
||||||
|
|
||||||
|
1.1) Remove any existing installation of `go`
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo rm -rf /usr/local/go
|
||||||
|
```
|
||||||
|
|
||||||
|
1.2) Install latest/required Go version (installing `go1.17.2`)
|
||||||
|
|
||||||
|
```
|
||||||
|
curl https://golang.org/dl/go1.17.2.linux-amd64.tar.gz
|
||||||
|
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.17.2.linux-amd64.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
1.3) Update env variables to include `go`
|
||||||
|
|
||||||
|
```
|
||||||
|
cat <<'EOF' >>$HOME/.profile
|
||||||
|
export GOROOT=/usr/local/go
|
||||||
|
export GOPATH=$HOME/go
|
||||||
|
export GO111MODULE=on
|
||||||
|
export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin
|
||||||
|
EOF
|
||||||
|
|
||||||
|
source $HOME/.profile
|
||||||
|
```
|
||||||
|
|
||||||
|
1.4) Check the version of go installed
|
||||||
|
|
||||||
|
```
|
||||||
|
go version
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2) Install required software packages
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt-get install git curl build-essential make jq -y
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3) Install `ethermint`
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/vulcanize/ethermint.git
|
||||||
|
cd ethermint
|
||||||
|
git fetch --all
|
||||||
|
git checkout v0.1.0-dev
|
||||||
|
make install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4) Verify your installation
|
||||||
|
|
||||||
|
```
|
||||||
|
ethermintd version --long
|
||||||
|
```
|
||||||
|
|
||||||
|
On running the above command, you should see a similar response like this. Make sure that the *version* and *commit
|
||||||
|
hash* are accurate
|
||||||
|
|
||||||
|
```
|
||||||
|
name: ethermint
|
||||||
|
server_name: ethermintd
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5) Initialize Node
|
||||||
|
|
||||||
|
**Not required if you have already initialized before**
|
||||||
|
|
||||||
|
```
|
||||||
|
ethermintd init <your-node-moniker> --chain-id ethermint_81337-1
|
||||||
|
```
|
||||||
|
|
||||||
|
On running the above command, node will be initialized with default configuration. (config files will be saved in node's
|
||||||
|
default home directory (~/.ethermintd/config)
|
||||||
|
|
||||||
|
NOTE: Backup node and validator keys . You will need to use these keys at a later point in time.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# B) Starting Node
|
||||||
|
|
||||||
|
## 1) Download Final Genesis
|
||||||
|
|
||||||
|
Use `curl` to download the genesis file
|
||||||
|
**Replace your **genesis** file with published genesis file**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl http://167.172.173.94:26657/genesis | jq .result.genesis > ~/.ethermintd/config/genesis.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify sha256 hash of genesis file with the below command
|
||||||
|
|
||||||
|
```
|
||||||
|
jq -S -c -M '' ~/.ethermintd/config/genesis.json | shasum -a 256
|
||||||
|
```
|
||||||
|
|
||||||
|
genesis sha256 hash should be
|
||||||
|
|
||||||
|
```
|
||||||
|
4e5b68b5652a608c44c33e669c84ac179d9c0e301f958b5448f037a53c5cbb4e
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2) Update Peers & Seeds in config.toml
|
||||||
|
|
||||||
|
```
|
||||||
|
peers="5ad2e6c35f2c84ff3ee31d89a95b34d92cb6afb1@157.230.101.237:26656,defc95b08547b6ef254723ad9621967a7e819020@161.35.223.44:26656"
|
||||||
|
sed -i.bak -e "s/^persistent_peers *=.*/persistent_peers = \"$peers\"/" ~/.ethermintd/config/config.toml
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3) Start the Full Node
|
||||||
|
|
||||||
|
#### 3.1) Start node as `systemctl` service
|
||||||
|
|
||||||
|
3.1.1) Create the service file
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo tee /etc/systemd/system/ethermintd.service > /dev/null <<EOF
|
||||||
|
[Unit]
|
||||||
|
Description=EthermintD Daemon
|
||||||
|
After=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=$USER
|
||||||
|
ExecStart=$(which ethermintd) start --gql-playground --gql-server
|
||||||
|
Restart=always
|
||||||
|
RestartSec=3
|
||||||
|
LimitNOFILE=65535
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
3.1.2) Load service and start
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable ethermintd
|
||||||
|
sudo systemctl start ethermintd
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
3.1.3) Check status of service
|
||||||
|
```
|
||||||
|
|
||||||
|
sudo systemctl status ethermintd
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
`NOTE:`
|
||||||
|
A helpful command here is `journalctl` that can be used to:
|
||||||
|
|
||||||
|
a) check logs
|
||||||
|
```
|
||||||
|
|
||||||
|
journalctl -u ethermintd
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
b) most recent logs
|
||||||
|
```
|
||||||
|
|
||||||
|
journalctl -xeu ethermintd
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
c) logs from previous day
|
||||||
|
```
|
||||||
|
|
||||||
|
journalctl --since "1 day ago" -u ethermintd
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
d) Check logs with follow flag
|
||||||
|
```
|
||||||
|
|
||||||
|
journalctl -f -u ethermintd
|
||||||
|
|
||||||
|
```
|
231
testnet/genesis-validators.md
Normal file
231
testnet/genesis-validators.md
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
# Setting up a Genesis Validator for Vulcanize Ethermint Testnet (ethermint_9000-1)
|
||||||
|
|
||||||
|
Hardware
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Supported
|
||||||
|
|
||||||
|
- **Operating System (OS):** Ubuntu 20.04
|
||||||
|
- **CPU:** 1 core
|
||||||
|
- **RAM:** 2GB
|
||||||
|
- **Storage:** 25GB SSD
|
||||||
|
|
||||||
|
#### Recommended
|
||||||
|
|
||||||
|
- **Operating System (OS):** Ubuntu 20.04
|
||||||
|
- **CPU:** 2 core
|
||||||
|
- **RAM:** 4GB
|
||||||
|
- **Storage:** 50GB SSD
|
||||||
|
|
||||||
|
# A) Setup
|
||||||
|
|
||||||
|
## 1) Install Golang (go)
|
||||||
|
|
||||||
|
1.1) Remove any existing installation of `go`
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo rm -rf /usr/local/go
|
||||||
|
```
|
||||||
|
|
||||||
|
1.2) Install latest/required Go version (installing `go1.17.2`)
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -O https://golang.org/dl/go1.17.2.linux-amd64.tar.gz
|
||||||
|
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.17.2.linux-amd64.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
1.3) Update env variables to include `go`
|
||||||
|
|
||||||
|
```
|
||||||
|
cat <<'EOF' >>$HOME/.profile
|
||||||
|
export GOROOT=/usr/local/go
|
||||||
|
export GOPATH=$HOME/go
|
||||||
|
export GO111MODULE=on
|
||||||
|
export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin
|
||||||
|
EOF
|
||||||
|
|
||||||
|
source $HOME/.profile
|
||||||
|
```
|
||||||
|
|
||||||
|
1.4) Check the version of go installed
|
||||||
|
|
||||||
|
```
|
||||||
|
go version
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2) Install required software packages
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt-get update && sudo apt-get install git curl build-essential make jq -y
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3) Install `ethermint`
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/vulcanize/ethermint.git
|
||||||
|
cd ethermint
|
||||||
|
git fetch --all
|
||||||
|
git checkout v0.1.0-dev
|
||||||
|
make install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4) Verify your installation
|
||||||
|
|
||||||
|
```
|
||||||
|
ethermintd version --long
|
||||||
|
```
|
||||||
|
|
||||||
|
On running the above command, you should see a similar response like this. Make sure that the *version* and *commit
|
||||||
|
hash* are accurate
|
||||||
|
|
||||||
|
```
|
||||||
|
name: ethermint
|
||||||
|
server_name: ethermintd
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5) Initialize Node
|
||||||
|
|
||||||
|
**Not required if you have already initialized before**
|
||||||
|
|
||||||
|
```
|
||||||
|
ethermintd init <your-node-moniker> --chain-id ethermint_81337-1
|
||||||
|
```
|
||||||
|
|
||||||
|
On running the above command, node will be initialized with default configuration. (config files will be saved in node's
|
||||||
|
default home directory (~/.ethermintd/config)
|
||||||
|
|
||||||
|
NOTE: Backup node and validator keys. You will need to use these keys at a later point in time.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6) Create Account keys
|
||||||
|
|
||||||
|
if you have participated in previous testnet and have mnemonic phrase, use below command to recover your account
|
||||||
|
|
||||||
|
```
|
||||||
|
ethermintd keys add <key-name> --recover
|
||||||
|
```
|
||||||
|
|
||||||
|
to create new account
|
||||||
|
|
||||||
|
```
|
||||||
|
ethermintd keys add <key-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: Save `mnemonic` and related account details (public key). You will need to use the need mnemonic/private key to
|
||||||
|
recover accounts at a later point in time.
|
||||||
|
|
||||||
|
## 7) Add Genesis Account
|
||||||
|
|
||||||
|
```
|
||||||
|
ethermintd add-genesis-account <key-name> 4500000000000000agnt --keyring-backend os
|
||||||
|
```
|
||||||
|
|
||||||
|
## 8) Create Your `gentx`
|
||||||
|
|
||||||
|
```
|
||||||
|
ethermintd gentx <key-name> 4500000000000000agnt \
|
||||||
|
--pubkey=$(ethermintd tendermint show-validator) \
|
||||||
|
--chain-id="ethermint_81337-1" \
|
||||||
|
--moniker="my-moniker" \
|
||||||
|
--website="https://yourweb.site" \
|
||||||
|
--details="description of my validator" \
|
||||||
|
--commission-rate="0.10" \
|
||||||
|
--commission-max-rate="0.20" \
|
||||||
|
--commission-max-change-rate="0.01" \
|
||||||
|
--min-self-delegation="1"
|
||||||
|
```
|
||||||
|
|
||||||
|
Note:
|
||||||
|
|
||||||
|
- `<key-name>` and `chain-id` are required. other flags are optional
|
||||||
|
- Don't change amount value while creating your gentx
|
||||||
|
- Genesis transaction file will be saved in `~/.ethermintd/config/gentx` folder
|
||||||
|
|
||||||
|
## 9) Submit Your gentx
|
||||||
|
|
||||||
|
Submit your `gentx` file to the [testnets]() in the format of
|
||||||
|
`<validator-moniker>-gentx.json`
|
||||||
|
|
||||||
|
NOTE: (Do NOT use space in the file name)
|
||||||
|
|
||||||
|
To submit the gentx file, follow the below process:
|
||||||
|
|
||||||
|
- Fork the [testnets]() repository
|
||||||
|
- Upload your gentx file in `ethermint_81337-1/config/gentxs` folder
|
||||||
|
- Submit Pull Request to [testnets]() with name `ADD <your-moniker> gentx`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Execute below instructions only after publishing of final genesis file**
|
||||||
|
|
||||||
|
genesis file will be published to [testnets/ethermint_9000-1]()
|
||||||
|
|
||||||
|
# B) Starting the validator
|
||||||
|
|
||||||
|
TBU
|
||||||
|
|
||||||
|
## 3) Start the Node
|
||||||
|
|
||||||
|
#### 3.1) Start node as `systemctl` service
|
||||||
|
|
||||||
|
3.1.1) Create the service file Note: this step is not required if you did setup before
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo tee /etc/systemd/system/ethermintd.service > /dev/null <<EOF
|
||||||
|
[Unit]
|
||||||
|
Description=ethermintd Daemon
|
||||||
|
After=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=$USER
|
||||||
|
ExecStart=$(which ethermintd) start
|
||||||
|
Restart=always
|
||||||
|
RestartSec=3
|
||||||
|
LimitNOFILE=65535
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
3.1.2) Load service and start
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable ethermintd
|
||||||
|
sudo systemctl start ethermintd
|
||||||
|
```
|
||||||
|
|
||||||
|
3.1.3) Check status of service
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo systemctl status ethermintd
|
||||||
|
```
|
||||||
|
|
||||||
|
`NOTE:`
|
||||||
|
A helpful command here is `journalctl` that can be used to:
|
||||||
|
|
||||||
|
a) check logs
|
||||||
|
|
||||||
|
```
|
||||||
|
journalctl -u ethermintd
|
||||||
|
```
|
||||||
|
|
||||||
|
b) most recent logs
|
||||||
|
|
||||||
|
```
|
||||||
|
journalctl -xeu ethermintd
|
||||||
|
```
|
||||||
|
|
||||||
|
c) logs from previous day
|
||||||
|
|
||||||
|
```
|
||||||
|
journalctl --since "1 day ago" -u ethermintd
|
||||||
|
```
|
||||||
|
|
||||||
|
d) Check logs with follow flag
|
||||||
|
|
||||||
|
```
|
||||||
|
journalctl -f -u ethermintd
|
||||||
|
```
|
232
testnet/multinode_testnet.sh
Normal file
232
testnet/multinode_testnet.sh
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
#/bin/sh
|
||||||
|
|
||||||
|
# clean the existed chain
|
||||||
|
rm -rf ~/.testethermint*
|
||||||
|
|
||||||
|
echo "Installing the require tools "
|
||||||
|
sudo apt-get install git curl build-essential make nohup jq -y
|
||||||
|
echo "Done Installing the tools"
|
||||||
|
|
||||||
|
command_exists() {
|
||||||
|
type "$1" &>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
if command_exists go; then
|
||||||
|
echo "Golang is already installed"
|
||||||
|
else
|
||||||
|
echo "Installing golang dependencies"
|
||||||
|
wget https://golang.org/dl/go1.17.2.linux-amd64.tar.gz
|
||||||
|
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.17.2.linux-amd64.tar.gz
|
||||||
|
|
||||||
|
echo "Updating the profile"
|
||||||
|
export GOPATH=$HOME/go
|
||||||
|
export GOROOT=/usr/local/go
|
||||||
|
export GOBIN=$GOPATH/bin
|
||||||
|
export PATH=$PATH:/usr/local/go/bin:$GOBIN
|
||||||
|
|
||||||
|
echo "" >>~/.profile
|
||||||
|
echo 'export GOPATH=$HOME/go' >>~/.profile
|
||||||
|
echo 'export GOROOT=/usr/local/go' >>~/.profile
|
||||||
|
echo 'export GOBIN=$GOPATH/bin' >>~/.profile
|
||||||
|
echo 'export PATH=$PATH:/usr/local/go/bin:$GOBIN' >>~/.profile
|
||||||
|
|
||||||
|
source ~/.profile
|
||||||
|
mkdir -p "$GOBIN"
|
||||||
|
mkdir -p $GOPATH/src/github.com
|
||||||
|
go version
|
||||||
|
fi
|
||||||
|
|
||||||
|
# chain env variables
|
||||||
|
export DAEMON_HOME=~/.testethermint
|
||||||
|
export CHAINID=ethermint_9000-1
|
||||||
|
export DENOM=uether
|
||||||
|
export GH_URL=https://github.com/vulcanize/ethermint.git
|
||||||
|
export CHAIN_VERSION=dev
|
||||||
|
export DAEMON=ethermintd
|
||||||
|
|
||||||
|
display_usage() {
|
||||||
|
printf "** Please check the exported values:: **\n Daemon : $DAEMON\n Denom : $DENOM\n ChainID : $CHAINID\n DaemonHome : $DAEMON_HOME\n \n Github URL : $GH_URL\n Chain Version : $CHAIN_VERSION\n"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -z $DAEMON ] || [ -z $DENOM ] || [ -z $CHAINID ] || [ -z $DAEMON_HOME ] || [ -z $GH_URL ] || [ -z $CHAIN_VERSION ]; then
|
||||||
|
display_usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "--------- Install $DAEMON ---------"
|
||||||
|
git clone -b $CHAIN_VERSION --single-branch $GH_URL && cd $(basename $_ .git)
|
||||||
|
git fetch && git checkout $CHAIN_VERSION
|
||||||
|
make install
|
||||||
|
|
||||||
|
cd $HOME
|
||||||
|
|
||||||
|
# check version
|
||||||
|
$DAEMON version --long
|
||||||
|
|
||||||
|
#echo "----------Create test keys-----------"
|
||||||
|
|
||||||
|
export DAEMON_HOME_1=$DAEMON_HOME-1
|
||||||
|
export DAEMON_HOME_2=$DAEMON_HOME-2
|
||||||
|
export DAEMON_HOME_3=$DAEMON_HOME-3
|
||||||
|
export DAEMON_HOME_4=$DAEMON_HOME-4
|
||||||
|
|
||||||
|
printf "DAEMON_HOME_1=$DAEMON_HOME_1\nDAEMON_HOME_2=$DAEMON_HOME_2\nDAEMON_HOME_3=$DAEMON_HOME_3\nDAEMON_HOME_4=$DAEMON_HOME_4\n"
|
||||||
|
|
||||||
|
rm -rf $DAEMON_HOME*
|
||||||
|
|
||||||
|
echo "-----Create daemon home directories if not exist------"
|
||||||
|
|
||||||
|
mkdir -p "$DAEMON_HOME_1"
|
||||||
|
mkdir -p "$DAEMON_HOME_2"
|
||||||
|
mkdir -p "$DAEMON_HOME_3"
|
||||||
|
mkdir -p "$DAEMON_HOME_4"
|
||||||
|
|
||||||
|
echo "--------Start initializing the chain ($CHAINID)---------"
|
||||||
|
|
||||||
|
$DAEMON init --chain-id $CHAINID $DAEMON_HOME_1 --home $DAEMON_HOME_1 --keyring-backend test
|
||||||
|
$DAEMON init --chain-id $CHAINID $DAEMON_HOME_2 --home $DAEMON_HOME_2 --keyring-backend test
|
||||||
|
$DAEMON init --chain-id $CHAINID $DAEMON_HOME_3 --home $DAEMON_HOME_3 --keyring-backend test
|
||||||
|
$DAEMON init --chain-id $CHAINID $DAEMON_HOME_4 --home $DAEMON_HOME_4 --keyring-backend test
|
||||||
|
|
||||||
|
echo "---------Creating four keys-------------"
|
||||||
|
|
||||||
|
$DAEMON keys add validator1 --home $DAEMON_HOME_1 --keyring-backend test
|
||||||
|
$DAEMON keys add validator2 --home $DAEMON_HOME_2 --keyring-backend test
|
||||||
|
$DAEMON keys add validator3 --home $DAEMON_HOME_3 --keyring-backend test
|
||||||
|
$DAEMON keys add validator4 --home $DAEMON_HOME_4 --keyring-backend test
|
||||||
|
|
||||||
|
echo "----------Genesis creation---------"
|
||||||
|
|
||||||
|
$DAEMON --home $DAEMON_HOME_1 add-genesis-account validator1 1000000000000$DENOM --keyring-backend test
|
||||||
|
$DAEMON --home $DAEMON_HOME_2 add-genesis-account validator2 1000000000000$DENOM --keyring-backend test
|
||||||
|
$DAEMON --home $DAEMON_HOME_3 add-genesis-account validator3 1000000000000$DENOM --keyring-backend test
|
||||||
|
$DAEMON --home $DAEMON_HOME_4 add-genesis-account validator4 1000000000000$DENOM --keyring-backend test
|
||||||
|
$DAEMON --home $DAEMON_HOME_1 add-genesis-account $($DAEMON keys show validator2 -a --home $DAEMON_HOME_2 --keyring-backend test) 1000000000000$DENOM
|
||||||
|
$DAEMON --home $DAEMON_HOME_1 add-genesis-account $($DAEMON keys show validator3 -a --home $DAEMON_HOME_3 --keyring-backend test) 1000000000000$DENOM
|
||||||
|
$DAEMON --home $DAEMON_HOME_1 add-genesis-account $($DAEMON keys show validator4 -a --home $DAEMON_HOME_4 --keyring-backend test) 1000000000000$DENOM
|
||||||
|
|
||||||
|
echo "--------Gentx--------"
|
||||||
|
|
||||||
|
$DAEMON gentx validator1 90000000000$DENOM --chain-id $CHAINID --keyring-backend test --home $DAEMON_HOME_1
|
||||||
|
$DAEMON gentx validator2 90000000000$DENOM --chain-id $CHAINID --keyring-backend test --home $DAEMON_HOME_2
|
||||||
|
$DAEMON gentx validator3 90000000000$DENOM --chain-id $CHAINID --keyring-backend test --home $DAEMON_HOME_3
|
||||||
|
$DAEMON gentx validator4 90000000000$DENOM --chain-id $CHAINID --keyring-backend test --home $DAEMON_HOME_4
|
||||||
|
|
||||||
|
echo "---------Copy all the genesis to $DAEMON_HOME_1----------"
|
||||||
|
|
||||||
|
cp $DAEMON_HOME_2/config/gentx/*.json $DAEMON_HOME_1/config/gentx/
|
||||||
|
cp $DAEMON_HOME_3/config/gentx/*.json $DAEMON_HOME_1/config/gentx/
|
||||||
|
cp $DAEMON_HOME_4/config/gentx/*.json $DAEMON_HOME_1/config/gentx/
|
||||||
|
|
||||||
|
echo "----------collect-gentxs------------"
|
||||||
|
|
||||||
|
$DAEMON collect-gentxs --home $DAEMON_HOME_1
|
||||||
|
|
||||||
|
echo "---------Updating $DAEMON_HOME_1 genesis.json ------------"
|
||||||
|
|
||||||
|
sed -i "s/172800000000000/600000000000/g" $DAEMON_HOME_1/config/genesis.json
|
||||||
|
sed -i "s/172800s/600s/g" $DAEMON_HOME_1/config/genesis.json
|
||||||
|
sed -i "s/stake/$DENOM/g" $DAEMON_HOME_1/config/genesis.json
|
||||||
|
|
||||||
|
echo "---------Distribute genesis.json of $DAEMON_HOME_1 to remaining nodes-------"
|
||||||
|
|
||||||
|
cp $DAEMON_HOME_1/config/genesis.json $DAEMON_HOME_2/config/
|
||||||
|
cp $DAEMON_HOME_1/config/genesis.json $DAEMON_HOME_3/config/
|
||||||
|
cp $DAEMON_HOME_1/config/genesis.json $DAEMON_HOME_4/config/
|
||||||
|
|
||||||
|
echo "---------Getting public IP address-----------"
|
||||||
|
|
||||||
|
IP="127.0.0.1"
|
||||||
|
echo "Public IP address: ${IP}"
|
||||||
|
|
||||||
|
echo "----------Update node-id of $DAEMON_HOME_1 in remaining nodes---------"
|
||||||
|
nodeID=$("${DAEMON}" tendermint show-node-id --home $DAEMON_HOME_1)
|
||||||
|
echo $nodeID
|
||||||
|
PERSISTENT_PEERS="$nodeID@$IP:16656"
|
||||||
|
echo "PERSISTENT_PEERS : $PERSISTENT_PEERS"
|
||||||
|
|
||||||
|
echo "----------Updating $DAEMON_HOME_1 chain config-----------"
|
||||||
|
|
||||||
|
sed -i 's#tcp://127.0.0.1:26657#tcp://0.0.0.0:16657#g' $DAEMON_HOME_1/config/config.toml
|
||||||
|
sed -i 's#tcp://0.0.0.0:26656#tcp://0.0.0.0:16656#g' $DAEMON_HOME_1/config/config.toml
|
||||||
|
sed -i '/persistent_peers =/c\persistent_peers = "'""'"' $DAEMON_HOME_1/config/config.toml
|
||||||
|
sed -i '/max_num_inbound_peers =/c\max_num_inbound_peers = 140' $DAEMON_HOME_1/config/config.toml
|
||||||
|
sed -i '/max_num_outbound_peers =/c\max_num_outbound_peers = 110' $DAEMON_HOME_1/config/config.toml
|
||||||
|
sed -i '/pprof_laddr =/c\# pprof_laddr = "localhost:6060"' $DAEMON_HOME_1/config/config.toml
|
||||||
|
sed -i '/allow_duplicate_ip =/c\allow_duplicate_ip = true' $DAEMON_HOME_1/config/config.toml
|
||||||
|
|
||||||
|
sed -i 's#0.0.0.0:9090#0.0.0.0:1090#g' $DAEMON_HOME_1/config/app.toml
|
||||||
|
sed -i 's#0.0.0.0:9091#0.0.0.0:1091#g' $DAEMON_HOME_1/config/app.toml
|
||||||
|
|
||||||
|
sed -i 's#0.0.0.0:8545#0.0.0.0:1545#g' $DAEMON_HOME_1/config/app.toml
|
||||||
|
sed -i 's#0.0.0.0:8546#0.0.0.0:1546#g' $DAEMON_HOME_1/config/app.toml
|
||||||
|
|
||||||
|
echo "----------Updating $DAEMON_HOME_2 chain config-----------"
|
||||||
|
|
||||||
|
sed -i 's#tcp://127.0.0.1:26657#tcp://0.0.0.0:26657#g' $DAEMON_HOME_2/config/config.toml
|
||||||
|
sed -i 's#tcp://0.0.0.0:26656#tcp://0.0.0.0:26656#g' $DAEMON_HOME_2/config/config.toml
|
||||||
|
sed -i '/persistent_peers =/c\persistent_peers = "'"$PERSISTENT_PEERS"'"' $DAEMON_HOME_2/config/config.toml
|
||||||
|
sed -i '/max_num_inbound_peers =/c\max_num_inbound_peers = 140' $DAEMON_HOME_2/config/config.toml
|
||||||
|
sed -i '/max_num_outbound_peers =/c\max_num_outbound_peers = 110' $DAEMON_HOME_2/config/config.toml
|
||||||
|
sed -i '/pprof_laddr =/c\# pprof_laddr = "localhost:6060"' $DAEMON_HOME_2/config/config.toml
|
||||||
|
sed -i '/allow_duplicate_ip =/c\allow_duplicate_ip = true' $DAEMON_HOME_2/config/config.toml
|
||||||
|
|
||||||
|
sed -i 's#0.0.0.0:9090#0.0.0.0:2090#g' $DAEMON_HOME_2/config/app.toml
|
||||||
|
sed -i 's#0.0.0.0:9091#0.0.0.0:2091#g' $DAEMON_HOME_2/config/app.toml
|
||||||
|
|
||||||
|
sed -i 's#0.0.0.0:8545#0.0.0.0:2545#g' $DAEMON_HOME_2/config/app.toml
|
||||||
|
sed -i 's#0.0.0.0:8546#0.0.0.0:2546#g' $DAEMON_HOME_2/config/app.toml
|
||||||
|
|
||||||
|
echo "----------Updating $DAEMON_HOME_3 chain config------------"
|
||||||
|
|
||||||
|
sed -i 's#tcp://127.0.0.1:26657#tcp://0.0.0.0:36657#g' $DAEMON_HOME_3/config/config.toml
|
||||||
|
sed -i 's#tcp://0.0.0.0:26656#tcp://0.0.0.0:36656#g' $DAEMON_HOME_3/config/config.toml
|
||||||
|
sed -i '/persistent_peers =/c\persistent_peers = "'"$PERSISTENT_PEERS"'"' $DAEMON_HOME_3/config/config.toml
|
||||||
|
sed -i '/max_num_inbound_peers =/c\max_num_inbound_peers = 140' $DAEMON_HOME_3/config/config.toml
|
||||||
|
sed -i '/max_num_outbound_peers =/c\max_num_outbound_peers = 110' $DAEMON_HOME_3/config/config.toml
|
||||||
|
sed -i '/pprof_laddr =/c\# pprof_laddr = "localhost:6060"' $DAEMON_HOME_3/config/config.toml
|
||||||
|
sed -i '/allow_duplicate_ip =/c\allow_duplicate_ip = true' $DAEMON_HOME_3/config/config.toml
|
||||||
|
|
||||||
|
sed -i 's#0.0.0.0:9090#0.0.0.0:3090#g' $DAEMON_HOME_3/config/app.toml
|
||||||
|
sed -i 's#0.0.0.0:9091#0.0.0.0:3091#g' $DAEMON_HOME_3/config/app.toml
|
||||||
|
|
||||||
|
sed -i 's#0.0.0.0:8545#0.0.0.0:3545#g' $DAEMON_HOME_3/config/app.toml
|
||||||
|
sed -i 's#0.0.0.0:8546#0.0.0.0:3546#g' $DAEMON_HOME_3/config/app.toml
|
||||||
|
|
||||||
|
echo "----------Updating $DAEMON_HOME_4 chain config------------"
|
||||||
|
|
||||||
|
sed -i 's#tcp://127.0.0.1:26657#tcp://0.0.0.0:46657#g' $DAEMON_HOME_4/config/config.toml
|
||||||
|
sed -i 's#tcp://0.0.0.0:26656#tcp://0.0.0.0:46656#g' $DAEMON_HOME_4/config/config.toml
|
||||||
|
sed -i '/persistent_peers =/c\persistent_peers = "'"$PERSISTENT_PEERS"'"' $DAEMON_HOME_4/config/config.toml
|
||||||
|
sed -i '/max_num_inbound_peers =/c\max_num_inbound_peers = 140' $DAEMON_HOME_4/config/config.toml
|
||||||
|
sed -i '/max_num_outbound_peers =/c\max_num_outbound_peers = 110' $DAEMON_HOME_4/config/config.toml
|
||||||
|
sed -i '/pprof_laddr =/c\# pprof_laddr = "localhost:6060"' $DAEMON_HOME_4/config/config.toml
|
||||||
|
sed -i '/allow_duplicate_ip =/c\allow_duplicate_ip = true' $DAEMON_HOME_4/config/config.toml
|
||||||
|
|
||||||
|
sed -i 's#0.0.0.0:9090#0.0.0.0:4090#g' $DAEMON_HOME_4/config/app.toml
|
||||||
|
sed -i 's#0.0.0.0:9091#0.0.0.0:4091#g' $DAEMON_HOME_4/config/app.toml
|
||||||
|
|
||||||
|
sed -i 's#0.0.0.0:8545#0.0.0.0:4545#g' $DAEMON_HOME_4/config/app.toml
|
||||||
|
sed -i 's#0.0.0.0:8546#0.0.0.0:4546#g' $DAEMON_HOME_4/config/app.toml
|
||||||
|
|
||||||
|
echo "starting the chains"
|
||||||
|
|
||||||
|
nohup $(which $DAEMON) start --gql-playground --gql-server --home $DAEMON_HOME_1 >$DAEMON_HOME_1.log &
|
||||||
|
sleep 5s
|
||||||
|
echo "Checking $DAEMON_HOME_1 chain status"
|
||||||
|
$DAEMON status --node tcp://localhost:16657
|
||||||
|
|
||||||
|
nohup $(which $DAEMON) start --gql-playground --gql-server --home $DAEMON_HOME_2 >$DAEMON_HOME_2.log &
|
||||||
|
sleep 5s
|
||||||
|
echo "Checking $DAEMON_HOME_2 chain status"
|
||||||
|
$DAEMON status --node tcp://localhost:26657
|
||||||
|
|
||||||
|
nohup $(which $DAEMON) start --gql-playground --gql-server --home $DAEMON_HOME_3 >$DAEMON_HOME_3.log &
|
||||||
|
sleep 5s
|
||||||
|
echo "Checking $DAEMON_HOME_3 chain status"
|
||||||
|
$DAEMON status --node tcp://localhost:36657
|
||||||
|
|
||||||
|
nohup $(which $DAEMON) start --gql-playground --gql-server --home $DAEMON_HOME_4 >$DAEMON_HOME_4.log &
|
||||||
|
sleep 5s
|
||||||
|
echo "Checking $DAEMON_HOME_4 chain status"
|
||||||
|
$DAEMON status --node tcp://localhost:46657
|
56
testnet/validator-node.md
Normal file
56
testnet/validator-node.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
### Create Validator Post Genesis
|
||||||
|
|
||||||
|
1. Run Full Node
|
||||||
|
2. Create Account and Get test tokens
|
||||||
|
3. Create Validator
|
||||||
|
|
||||||
|
### 1.Run Full Node
|
||||||
|
|
||||||
|
- Check "[Run Full Node](full-node.md)" section to Run a Full Node
|
||||||
|
|
||||||
|
### 2. Create Account & Get test tokens
|
||||||
|
|
||||||
|
```
|
||||||
|
ethermintd keys add <key-name> --keyring-backend test
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: Save `mnemonic` and related account details (public key). You will need to use the need mnemonic/private key to
|
||||||
|
recover accounts at a later point in time.
|
||||||
|
|
||||||
|
##### Get Test tokens from faucet
|
||||||
|
|
||||||
|
- Open this link : http://167.172.173.94:1314/ and paste your account
|
||||||
|
- 1 gnt = 10^18 agnt
|
||||||
|
- Each Transaction you will get 500gnt
|
||||||
|
- Total Tokens 5000gnt for account
|
||||||
|
|
||||||
|
### 3.Create Validator
|
||||||
|
|
||||||
|
- ##### Check full node sync status
|
||||||
|
|
||||||
|
`ethermintd status 2>&1 | jq -r ".SyncInfo"`
|
||||||
|
|
||||||
|
`catching_up: false` means node is completely synced
|
||||||
|
- ##### Create validator
|
||||||
|
|
||||||
|
`Note:` Only execute below transaction after complete sync of your full node
|
||||||
|
|
||||||
|
Please replace `key_name` with your key name and `moniker` also
|
||||||
|
|
||||||
|
```
|
||||||
|
ethermintd tx staking create-validator \
|
||||||
|
--amount=4500000000000000000000agnt \
|
||||||
|
--pubkey=$(ethermintd tendermint show-validator) \
|
||||||
|
--moniker="my-moniker" \
|
||||||
|
--website="https://myweb.site" \
|
||||||
|
--details="description of your validator" \
|
||||||
|
--chain-id="ethermint_81337-1" \
|
||||||
|
--commission-rate="0.10" \
|
||||||
|
--commission-max-rate="0.20" \
|
||||||
|
--commission-max-change-rate="0.01" \
|
||||||
|
--min-self-delegation="1" \
|
||||||
|
--gas="auto" \
|
||||||
|
--gas-adjustment="1.2" \
|
||||||
|
--gas-prices="0.025agnt" \
|
||||||
|
--from=<key_name>
|
||||||
|
```
|
52
utils/json.go
Normal file
52
utils/json.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2020 Wireline, Inc.
|
||||||
|
//
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
canonicalJson "github.com/gibson042/canonicaljson-go"
|
||||||
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
|
mh "github.com/multiformats/go-multihash"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GenerateHash returns the hash of the canonicalized JSON input.
|
||||||
|
func GenerateHash(json map[string]interface{}) (string, []byte, error) {
|
||||||
|
content, err := canonicalJson.Marshal(json)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cid, err := CIDFromJSONBytes(content)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cid, content, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CIDFromJSONBytes returns CID (cbor) for json (as bytes).
|
||||||
|
func CIDFromJSONBytes(content []byte) (string, error) {
|
||||||
|
cid, err := cbor.FromJSON(bytes.NewReader(content), mh.SHA2_256, -1)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cid.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAttributeAsString returns a map attribute as string, if possible.
|
||||||
|
func GetAttributeAsString(obj map[string]interface{}, attr string) (string, error) {
|
||||||
|
if value, ok := obj[attr]; ok {
|
||||||
|
if valueStr, ok := value.(string); ok {
|
||||||
|
return valueStr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", errors.New("attribute not of string type")
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", errors.New("attribute not found")
|
||||||
|
}
|
25
utils/mnemonic.go
Normal file
25
utils/mnemonic.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2020 Wireline, Inc.
|
||||||
|
//
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import "github.com/cosmos/go-bip39"
|
||||||
|
|
||||||
|
const (
|
||||||
|
mnemonicEntropySize = 256
|
||||||
|
)
|
||||||
|
|
||||||
|
func GenerateMnemonic() (string, error) {
|
||||||
|
entropySeed, err := bip39.NewEntropy(mnemonicEntropySize)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
mnemonic, err := bip39.NewMnemonic(entropySeed[:])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return mnemonic, nil
|
||||||
|
}
|
52
utils/types.go
Normal file
52
utils/types.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2020 Wireline, Inc.
|
||||||
|
//
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
set "github.com/deckarep/golang-set"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Int64ToBytes(num int64) []byte {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
binary.Write(buf, binary.BigEndian, num)
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetToSlice(set set.Set) []string {
|
||||||
|
names := []string{}
|
||||||
|
|
||||||
|
for name := range set.Iter() {
|
||||||
|
if name, ok := name.(string); ok && name != "" {
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.SliceStable(names, func(i, j int) bool { return names[i] < names[j] })
|
||||||
|
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceToSet(names []string) set.Set {
|
||||||
|
set := set.NewThreadUnsafeSet()
|
||||||
|
|
||||||
|
for _, name := range names {
|
||||||
|
if name != "" {
|
||||||
|
set.Add(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
|
func AppendUnique(list []string, element string) []string {
|
||||||
|
set := SliceToSet(list)
|
||||||
|
set.Add(element)
|
||||||
|
|
||||||
|
return SetToSlice(set)
|
||||||
|
}
|
298
x/auction/README.md
Normal file
298
x/auction/README.md
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
# Auction Module CLI Commands
|
||||||
|
|
||||||
|
## Build the Chain
|
||||||
|
|
||||||
|
The following command builds the Ethermint daemon and places the binary in the `build` directory
|
||||||
|
|
||||||
|
```
|
||||||
|
make build
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Setup the Chain
|
||||||
|
|
||||||
|
The following steps need to be followed only before running the chain for the first time.
|
||||||
|
|
||||||
|
1. Add the root key:
|
||||||
|
```
|
||||||
|
./build/ethermintd keys add root
|
||||||
|
```
|
||||||
|
Keep a note of the keyring passphrase if you set it.
|
||||||
|
2. Init the chain:
|
||||||
|
```
|
||||||
|
./build/ethermintd init test-moniker --chain-id ethermint_9000-1
|
||||||
|
```
|
||||||
|
3. Add genesis account:
|
||||||
|
```
|
||||||
|
./build/ethermintd add-genesis-account $(./build/ethermintd keys show root -a) 1000000000000000000aphoton,1000000000000000000stake
|
||||||
|
```
|
||||||
|
4. Make a genesis tx:
|
||||||
|
```
|
||||||
|
./build/ethermintd gentx root 1000000000000000000stake --chain-id ethermint_9000-1
|
||||||
|
```
|
||||||
|
5. Collect gentxs:
|
||||||
|
```
|
||||||
|
./build/ethermintd collect-gentxs
|
||||||
|
```
|
||||||
|
|
||||||
|
The chain can now be started using:
|
||||||
|
|
||||||
|
```
|
||||||
|
./build/ethermintd start
|
||||||
|
```
|
||||||
|
|
||||||
|
## Querying the Params
|
||||||
|
|
||||||
|
The following command will dislay the default params for the `auction` module:
|
||||||
|
|
||||||
|
```
|
||||||
|
# ./build/ethermintd q auction params -o json | jq
|
||||||
|
|
||||||
|
{
|
||||||
|
"params": {
|
||||||
|
"commits_duration": "0s",
|
||||||
|
"reveals_duration": "0s",
|
||||||
|
"commit_fee": {
|
||||||
|
"denom": "",
|
||||||
|
"amount": "0"
|
||||||
|
},
|
||||||
|
"reveal_fee": {
|
||||||
|
"denom": "",
|
||||||
|
"amount": "0"
|
||||||
|
},
|
||||||
|
"minimum_bid": {
|
||||||
|
"denom": "",
|
||||||
|
"amount": "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Auction TX CLI Commands
|
||||||
|
|
||||||
|
### Create Auction
|
||||||
|
|
||||||
|
```
|
||||||
|
# ./build/ethermintd tx auction create 100s 100s 10aphoton 10aphoton 1000aphoton --from root --chain-id $(./build/ethermintd status | jq .NodeInfo.network -r)
|
||||||
|
|
||||||
|
Enter keyring passphrase:
|
||||||
|
|
||||||
|
{"body":{"messages":[{"@type":"/vulcanize.auction.v1beta1.MsgCreateAuction","commits_duration":"100s","reveals_duration":"100s","commit_fee":{"denom":"aphoton","amount":"10"},"reveal_fee":{"denom":"aphoton","amount":"10"},"minimum_bid":{"denom":"aphoton","amount":"1000"},"signer":"ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
|
||||||
|
|
||||||
|
confirm transaction before signing and broadcasting [y/N]: y
|
||||||
|
|
||||||
|
code: 0
|
||||||
|
codespace: ""
|
||||||
|
data: ""
|
||||||
|
gas_used: "0"
|
||||||
|
gas_wanted: "0"
|
||||||
|
height: "0"
|
||||||
|
info: ""
|
||||||
|
logs: []
|
||||||
|
raw_log: '[]'
|
||||||
|
timestamp: ""
|
||||||
|
tx: null
|
||||||
|
txhash: ECAD6DF1ECA763FBD26EB7C2C0B77425FFE2FBEA2BEC57CE0FBC173AE0F45298
|
||||||
|
```
|
||||||
|
|
||||||
|
### Commit Bid
|
||||||
|
|
||||||
|
```
|
||||||
|
# ./build/ethermintd tx auction commit-bid e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d 2000aphoton --from root --chain-id $(./build/ethermintd status | jq .NodeInfo.network -r)
|
||||||
|
|
||||||
|
Enter keyring passphrase:
|
||||||
|
|
||||||
|
{"body":{"messages":[{"@type":"/vulcanize.auction.v1beta1.MsgCommitBid","auction_id":"e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d","commit_hash":"bafyreibt4twofrc3xi2es27cfrroy346iy6lr3gkw33i5dltkqqarlyltm","signer":"ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
|
||||||
|
|
||||||
|
confirm transaction before signing and broadcasting [y/N]: y
|
||||||
|
|
||||||
|
code: 0
|
||||||
|
codespace: ""
|
||||||
|
data: ""
|
||||||
|
gas_used: "0"
|
||||||
|
gas_wanted: "0"
|
||||||
|
height: "0"
|
||||||
|
info: ""
|
||||||
|
logs: []
|
||||||
|
raw_log: '[]'
|
||||||
|
timestamp: ""
|
||||||
|
tx: null
|
||||||
|
txhash: 71D8CF34026E32A3A34C2C2D4ADF25ABC8D7943A4619761BE27F196603D91B9D
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reveal Bid
|
||||||
|
|
||||||
|
```
|
||||||
|
# ./build/ethermintd tx auction reveal-bid e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d root-bafyreibt4twofrc3xi2es27cfrroy346iy6lr3gkw33i5dltkqqarlyltm.json --from root --chain-id $(./build/ethermintd status | jq .NodeInfo.network -r)
|
||||||
|
|
||||||
|
Enter keyring passphrase:
|
||||||
|
|
||||||
|
{"body":{"messages":[{"@type":"/vulcanize.auction.v1beta1.MsgRevealBid","auction_id":"e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d","reveal":"7b2261756374696f6e4964223a2265376431346337653761366437353337636264623866626536326632326231353533633265663463653337303561646137633238663830666166326662653064222c22626964416d6f756e74223a22323030306170686f746f6e222c2262696464657241646472657373223a226574686d316c37637374777466326c76657632376b613637633233796b376d6d6a38616437746574707163222c22636861696e4964223a2265746865726d696e745f393030302d31222c226e6f697365223a22636c69666620737566666572206472616d6120676f7370656c2077656173656c207061706572206c696272617279206469736f726465722063757276652073706f74206375727461696e207a6562726120696e76657374206465766f74652072656e64657220636c6970207377616c6c6f77206d6f6e6b6579206f62736572766520726573706f6e7365206c696e6b206372616e6520766961626c6520736576656e227d","signer":"ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
|
||||||
|
|
||||||
|
confirm transaction before signing and broadcasting [y/N]: y
|
||||||
|
|
||||||
|
code: 0
|
||||||
|
codespace: ""
|
||||||
|
data: ""
|
||||||
|
gas_used: "0"
|
||||||
|
gas_wanted: "0"
|
||||||
|
height: "0"
|
||||||
|
info: ""
|
||||||
|
logs: []
|
||||||
|
raw_log: '[]'
|
||||||
|
timestamp: ""
|
||||||
|
tx: null
|
||||||
|
txhash: 4D1C0B3DDA4050F9BB32240FBD5234229E5C32543C1A0A78033B9531EB0CF8BA
|
||||||
|
```
|
||||||
|
|
||||||
|
## Auction Query CLI Commands
|
||||||
|
|
||||||
|
### List Auctions
|
||||||
|
|
||||||
|
```
|
||||||
|
# ./build/ethermintd q auction list
|
||||||
|
|
||||||
|
auctions:
|
||||||
|
auctions:
|
||||||
|
- commit_fee:
|
||||||
|
amount: "10"
|
||||||
|
denom: aphoton
|
||||||
|
commits_end_time: "2021-09-30T07:57:07.933412800Z"
|
||||||
|
create_time: "2021-09-30T07:55:27.933412800Z"
|
||||||
|
id: e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d
|
||||||
|
minimum_bid:
|
||||||
|
amount: "1000"
|
||||||
|
denom: aphoton
|
||||||
|
owner_address: ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc
|
||||||
|
reveal_fee:
|
||||||
|
amount: "10"
|
||||||
|
denom: aphoton
|
||||||
|
reveals_end_time: "2021-09-30T07:58:47.933412800Z"
|
||||||
|
status: commit
|
||||||
|
winner_address: ""
|
||||||
|
winning_bid:
|
||||||
|
amount: "0"
|
||||||
|
denom: ""
|
||||||
|
winning_price:
|
||||||
|
amount: "0"
|
||||||
|
denom: ""
|
||||||
|
pagination: null
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get Bid
|
||||||
|
|
||||||
|
```
|
||||||
|
# ./build/ethermintd q auction get-bid e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0e ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc
|
||||||
|
|
||||||
|
bid:
|
||||||
|
auction_id: e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d
|
||||||
|
bid_amount:
|
||||||
|
amount: "0"
|
||||||
|
denom: ""
|
||||||
|
bidder_address: ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc
|
||||||
|
commit_fee:
|
||||||
|
amount: "10"
|
||||||
|
denom: aphoton
|
||||||
|
commit_hash: bafyreibt4twofrc3xi2es27cfrroy346iy6lr3gkw33i5dltkqqarlyltm
|
||||||
|
commit_time: "2021-09-30T08:49:48.358878200Z"
|
||||||
|
reveal_fee:
|
||||||
|
amount: "10"
|
||||||
|
denom: aphoton
|
||||||
|
reveal_time: "0001-01-01T00:00:00Z"
|
||||||
|
status: commit
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get All Bids for an Auction
|
||||||
|
|
||||||
|
```
|
||||||
|
./build/ethermintd q auction get-bids e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d
|
||||||
|
|
||||||
|
bids:
|
||||||
|
- auction_id: e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d
|
||||||
|
bid_amount:
|
||||||
|
amount: "0"
|
||||||
|
denom: ""
|
||||||
|
bidder_address: ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc
|
||||||
|
commit_fee:
|
||||||
|
amount: "10"
|
||||||
|
denom: aphoton
|
||||||
|
commit_hash: bafyreibt4twofrc3xi2es27cfrroy346iy6lr3gkw33i5dltkqqarlyltm
|
||||||
|
commit_time: "2021-09-30T08:49:48.358878200Z"
|
||||||
|
reveal_fee:
|
||||||
|
amount: "10"
|
||||||
|
denom: aphoton
|
||||||
|
reveal_time: "0001-01-01T00:00:00Z"
|
||||||
|
status: commit
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get Auction by AuctionID
|
||||||
|
|
||||||
|
```
|
||||||
|
# ./build/ethermintd q auction get e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d
|
||||||
|
|
||||||
|
auction:
|
||||||
|
commit_fee:
|
||||||
|
amount: "10"
|
||||||
|
denom: aphoton
|
||||||
|
commits_end_time: "2021-09-30T07:57:07.933412800Z"
|
||||||
|
create_time: "2021-09-30T07:55:27.933412800Z"
|
||||||
|
id: e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d
|
||||||
|
minimum_bid:
|
||||||
|
amount: "1000"
|
||||||
|
denom: aphoton
|
||||||
|
owner_address: ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc
|
||||||
|
reveal_fee:
|
||||||
|
amount: "10"
|
||||||
|
denom: aphoton
|
||||||
|
reveals_end_time: "2021-09-30T07:58:47.933412800Z"
|
||||||
|
status: commit
|
||||||
|
winner_address: ""
|
||||||
|
winning_bid:
|
||||||
|
amount: "0"
|
||||||
|
denom: ""
|
||||||
|
winning_price:
|
||||||
|
amount: "0"
|
||||||
|
denom: ""
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get Auction by Bidder
|
||||||
|
|
||||||
|
```
|
||||||
|
# ./build/ethermintd q auction query-by-owner ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc
|
||||||
|
|
||||||
|
auctions:
|
||||||
|
auctions:
|
||||||
|
- commit_fee:
|
||||||
|
amount: "10"
|
||||||
|
denom: aphoton
|
||||||
|
commits_end_time: "2021-09-30T07:57:07.933412800Z"
|
||||||
|
create_time: "2021-09-30T07:55:27.933412800Z"
|
||||||
|
id: e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d
|
||||||
|
minimum_bid:
|
||||||
|
amount: "1000"
|
||||||
|
denom: aphoton
|
||||||
|
owner_address: ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc
|
||||||
|
reveal_fee:
|
||||||
|
amount: "10"
|
||||||
|
denom: aphoton
|
||||||
|
reveals_end_time: "2021-09-30T07:58:47.933412800Z"
|
||||||
|
status: commit
|
||||||
|
winner_address: ""
|
||||||
|
winning_bid:
|
||||||
|
amount: "0"
|
||||||
|
denom: ""
|
||||||
|
winning_price:
|
||||||
|
amount: "0"
|
||||||
|
denom: ""
|
||||||
|
```
|
||||||
|
|
||||||
|
### Query Account Balance
|
||||||
|
|
||||||
|
```
|
||||||
|
# ./build/ethermintd q auction balance
|
||||||
|
|
||||||
|
balance:
|
||||||
|
- amount: "20"
|
||||||
|
denom: aphoton
|
||||||
|
```
|
13
x/auction/abci.go
Normal file
13
x/auction/abci.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package auction
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
"github.com/tharsis/ethermint/x/auction/keeper"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EndBlocker is called every block, returns updated validator set.
|
||||||
|
func EndBlocker(ctx sdk.Context, k keeper.Keeper) []abci.ValidatorUpdate {
|
||||||
|
k.EndBlockerProcessAuctions(ctx)
|
||||||
|
return []abci.ValidatorUpdate{}
|
||||||
|
}
|
263
x/auction/client/cli/query.go
Normal file
263
x/auction/client/cli/query.go
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
|
"github.com/cosmos/cosmos-sdk/version"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetQueryCmd() *cobra.Command {
|
||||||
|
auctionQueryCmd := &cobra.Command{
|
||||||
|
Use: types.ModuleName,
|
||||||
|
Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName),
|
||||||
|
DisableFlagParsing: true,
|
||||||
|
SuggestionsMinimumDistance: 2,
|
||||||
|
RunE: client.ValidateCmd,
|
||||||
|
}
|
||||||
|
auctionQueryCmd.AddCommand(
|
||||||
|
GetCmdList(),
|
||||||
|
GetCmdGetAuction(),
|
||||||
|
GetCmdGetBid(),
|
||||||
|
GetCmdGetBids(),
|
||||||
|
GetCmdAuctionsByBidder(),
|
||||||
|
GetCmdAuctionsByOwner(),
|
||||||
|
GetCmdQueryParams(),
|
||||||
|
GetCmdBalance(),
|
||||||
|
)
|
||||||
|
|
||||||
|
return auctionQueryCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCmdList queries all auctions.
|
||||||
|
func GetCmdList() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "list",
|
||||||
|
Short: "List auctions.",
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
queryClient := types.NewQueryClient(clientCtx)
|
||||||
|
res, err := queryClient.Auctions(cmd.Context(), &types.AuctionsRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientCtx.PrintProto(res)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.AddQueryFlagsToCmd(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCmdGetBid queries an auction bid.
|
||||||
|
func GetCmdGetBid() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "get-bid [auction-id] [bidder]",
|
||||||
|
Short: "Get auction bid.",
|
||||||
|
Args: cobra.ExactArgs(2),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
id := args[0]
|
||||||
|
bidder := args[1]
|
||||||
|
|
||||||
|
queryClient := types.NewQueryClient(clientCtx)
|
||||||
|
res, err := queryClient.GetBid(cmd.Context(), &types.BidRequest{AuctionId: id, Bidder: bidder})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientCtx.PrintProto(res)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.AddQueryFlagsToCmd(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCmdGetBids queries all auction bids.
|
||||||
|
func GetCmdGetBids() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "get-bids [auction-id]",
|
||||||
|
Short: "Get all auction bids.",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
id := args[0]
|
||||||
|
|
||||||
|
queryClient := types.NewQueryClient(clientCtx)
|
||||||
|
res, err := queryClient.GetBids(cmd.Context(), &types.BidsRequest{AuctionId: id})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientCtx.PrintProto(res)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.AddQueryFlagsToCmd(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCmdGetAuction queries an auction.
|
||||||
|
func GetCmdGetAuction() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "get [ID]",
|
||||||
|
Short: "Get auction.",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
id := args[0]
|
||||||
|
|
||||||
|
queryClient := types.NewQueryClient(clientCtx)
|
||||||
|
res, err := queryClient.GetAuction(cmd.Context(), &types.AuctionRequest{Id: id})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientCtx.PrintProto(res)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.AddQueryFlagsToCmd(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCmdAuctionsByBidder queries auctions by bidder.
|
||||||
|
func GetCmdAuctionsByBidder() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "query-by-bidder [address]",
|
||||||
|
Short: "Query auctions by bidder.",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
address := args[0]
|
||||||
|
|
||||||
|
queryClient := types.NewQueryClient(clientCtx)
|
||||||
|
res, err := queryClient.AuctionsByBidder(cmd.Context(), &types.AuctionsByBidderRequest{BidderAddress: address})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientCtx.PrintProto(res)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.AddQueryFlagsToCmd(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCmdAuctionsByOwner queries auctions by owner
|
||||||
|
func GetCmdAuctionsByOwner() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "query-by-owner [address]",
|
||||||
|
Short: "Query auctions by owner/creator.",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
address := args[0]
|
||||||
|
|
||||||
|
queryClient := types.NewQueryClient(clientCtx)
|
||||||
|
res, err := queryClient.AuctionsByOwner(cmd.Context(), &types.AuctionsByOwnerRequest{OwnerAddress: address})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientCtx.PrintProto(res)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.AddQueryFlagsToCmd(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCmdQueryParams implements the params query command.
|
||||||
|
func GetCmdQueryParams() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "params",
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
Short: "Query the current auction parameters information.",
|
||||||
|
Long: strings.TrimSpace(
|
||||||
|
fmt.Sprintf(`Query values set as auction parameters.
|
||||||
|
Example:
|
||||||
|
$ %s query auction params
|
||||||
|
`,
|
||||||
|
version.AppName,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
queryClient := types.NewQueryClient(clientCtx)
|
||||||
|
res, err := queryClient.QueryParams(cmd.Context(), &types.QueryParamsRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientCtx.PrintProto(res)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.AddQueryFlagsToCmd(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCmdBalance queries the auction module account balance.
|
||||||
|
func GetCmdBalance() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "balance",
|
||||||
|
Short: "Get auction module account balance.",
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
queryClient := types.NewQueryClient(clientCtx)
|
||||||
|
res, err := queryClient.Balance(cmd.Context(), &types.BalanceRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientCtx.PrintProto(res)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.AddQueryFlagsToCmd(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
187
x/auction/client/cli/tx.go
Normal file
187
x/auction/client/cli/tx.go
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
|
"github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
|
||||||
|
wnsUtils "github.com/tharsis/ethermint/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetTxCmd returns transaction commands for this module.
|
||||||
|
func GetTxCmd() *cobra.Command {
|
||||||
|
auctionTxCmd := &cobra.Command{
|
||||||
|
Use: types.ModuleName,
|
||||||
|
Short: "Auction transactions subcommands",
|
||||||
|
DisableFlagParsing: true,
|
||||||
|
SuggestionsMinimumDistance: 2,
|
||||||
|
RunE: client.ValidateCmd,
|
||||||
|
}
|
||||||
|
|
||||||
|
auctionTxCmd.AddCommand(
|
||||||
|
GetCmdCreateAuction(),
|
||||||
|
GetCmdCommitBid(),
|
||||||
|
GetCmdRevealBid(),
|
||||||
|
)
|
||||||
|
|
||||||
|
return auctionTxCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCmdCreateAuction() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "create [commits-duration] [reveals-duration] [commit-fee] [reveal-fee] [minimum-bid]",
|
||||||
|
Short: "Create auction.",
|
||||||
|
Args: cobra.ExactArgs(5),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientTxContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
commitsDuration, err := time.ParseDuration(args[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
revealsDuration, err := time.ParseDuration(args[1])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
commitFee, err := sdk.ParseCoinNormalized(args[2])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
revealFee, err := sdk.ParseCoinNormalized(args[3])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
minimumBid, err := sdk.ParseCoinNormalized(args[4])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
params := types.Params{
|
||||||
|
CommitsDuration: commitsDuration,
|
||||||
|
RevealsDuration: revealsDuration,
|
||||||
|
CommitFee: commitFee,
|
||||||
|
RevealFee: revealFee,
|
||||||
|
MinimumBid: minimumBid,
|
||||||
|
}
|
||||||
|
msg := types.NewMsgCreateAuction(params, clientCtx.GetFromAddress())
|
||||||
|
err = msg.ValidateBasic()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.AddTxFlagsToCmd(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCmdCommitBid is the CLI command for committing a bid.
|
||||||
|
func GetCmdCommitBid() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "commit-bid [auction-id] [bid-amount]",
|
||||||
|
Short: "Commit sealed bid.",
|
||||||
|
Args: cobra.ExactArgs(2),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientTxContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
bidAmount, err := sdk.ParseCoinNormalized(args[1])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mnemonic, err := wnsUtils.GenerateMnemonic()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
chainID := viper.GetString("chain-id")
|
||||||
|
auctionID := args[0]
|
||||||
|
|
||||||
|
reveal := map[string]interface{}{
|
||||||
|
"chainId": chainID,
|
||||||
|
"auctionId": auctionID,
|
||||||
|
"bidderAddress": clientCtx.GetFromAddress().String(),
|
||||||
|
"bidAmount": bidAmount.String(),
|
||||||
|
"noise": mnemonic,
|
||||||
|
}
|
||||||
|
|
||||||
|
commitHash, content, err := wnsUtils.GenerateHash(reveal)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save reveal file.
|
||||||
|
ioutil.WriteFile(fmt.Sprintf("%s-%s.json", clientCtx.GetFromName(), commitHash), content, 0600)
|
||||||
|
|
||||||
|
msg := types.NewMsgCommitBid(auctionID, commitHash, clientCtx.GetFromAddress())
|
||||||
|
err = msg.ValidateBasic()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.AddTxFlagsToCmd(cmd)
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCmdRevealBid is the CLI command for revealing a bid.
|
||||||
|
func GetCmdRevealBid() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "reveal-bid [auction-id] [reveal-file-path]",
|
||||||
|
Short: "Reveal bid.",
|
||||||
|
Args: cobra.ExactArgs(2),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientTxContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
auctionID := args[0]
|
||||||
|
revealFilePath := args[1]
|
||||||
|
|
||||||
|
revealBytes, err := ioutil.ReadFile(revealFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := types.NewMsgRevealBid(auctionID, hex.EncodeToString(revealBytes), clientCtx.GetFromAddress())
|
||||||
|
err = msg.ValidateBasic()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.AddTxFlagsToCmd(cmd)
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
15
x/auction/client/testutil/cli_test.go
Normal file
15
x/auction/client/testutil/cli_test.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package testutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
"github.com/tharsis/ethermint/testutil/network"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIntegrationTestSuite(t *testing.T) {
|
||||||
|
cfg := network.DefaultConfig()
|
||||||
|
cfg.NumValidators = 1
|
||||||
|
suite.Run(t, NewIntegrationTestSuite(cfg))
|
||||||
|
}
|
77
x/auction/client/testutil/common.go
Normal file
77
x/auction/client/testutil/common.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package testutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
"github.com/tharsis/ethermint/testutil/network"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IntegrationTestSuite struct {
|
||||||
|
suite.Suite
|
||||||
|
|
||||||
|
cfg network.Config
|
||||||
|
network *network.Network
|
||||||
|
defaultAuctionID string
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ownerAccount = "owner"
|
||||||
|
bidderAccount = "bidder"
|
||||||
|
ownerAddress string
|
||||||
|
bidderAddress string
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
|
||||||
|
return &IntegrationTestSuite{cfg: cfg}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) SetupSuite() {
|
||||||
|
s.T().Log("setting up integration test suite")
|
||||||
|
|
||||||
|
s.network = network.New(s.T(), s.cfg)
|
||||||
|
|
||||||
|
_, err := s.network.WaitForHeight(1)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
// setting up random owner and bidder accounts
|
||||||
|
s.createAccountWithBalance(ownerAccount, &ownerAddress)
|
||||||
|
s.createAccountWithBalance(bidderAccount, &bidderAddress)
|
||||||
|
|
||||||
|
s.defaultAuctionID = s.createAuctionAndBid(true, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) TearDownSuite() {
|
||||||
|
s.T().Log("tearing down integration test suite")
|
||||||
|
s.network.Cleanup()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) createAccountWithBalance(accountName string, accountAddress *string) {
|
||||||
|
val := s.network.Validators[0]
|
||||||
|
sr := s.Require()
|
||||||
|
consPrivKey := ed25519.GenPrivKey()
|
||||||
|
consPubKeyBz, err := s.cfg.Codec.MarshalInterfaceJSON(consPrivKey.PubKey())
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.NotNil(consPubKeyBz)
|
||||||
|
|
||||||
|
info, _, err := val.ClientCtx.Keyring.NewMnemonic(accountName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
|
||||||
|
sr.NoError(err)
|
||||||
|
|
||||||
|
newAddr := sdk.AccAddress(info.GetPubKey().Address())
|
||||||
|
_, err = banktestutil.MsgSendExec(
|
||||||
|
val.ClientCtx,
|
||||||
|
val.Address,
|
||||||
|
newAddr,
|
||||||
|
sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200000))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||||
|
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||||
|
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||||
|
)
|
||||||
|
sr.NoError(err)
|
||||||
|
*accountAddress = newAddr.String()
|
||||||
|
}
|
255
x/auction/client/testutil/grpc.go
Normal file
255
x/auction/client/testutil/grpc.go
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
package testutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/rest"
|
||||||
|
auctiontypes "github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
randomAuctionID = "randomAuctionID"
|
||||||
|
randomBidderAddress = "randomBidderAddress"
|
||||||
|
randomOwnerAddress = "randomOwnerAddress"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestGetAllAuctionsGrpc() {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
reqUrl := fmt.Sprintf("%s/vulcanize/auction/v1beta1/auctions", val.APIAddress)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
url string
|
||||||
|
errorMsg string
|
||||||
|
isErrorExpected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"invalid request to get all auctions",
|
||||||
|
reqUrl + randomAuctionID,
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valid request to get all auctions",
|
||||||
|
reqUrl,
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.msg, func() {
|
||||||
|
resp, err := rest.GetRequest(tc.url)
|
||||||
|
if tc.isErrorExpected {
|
||||||
|
sr.Contains(string(resp), tc.errorMsg)
|
||||||
|
} else {
|
||||||
|
sr.NoError(err)
|
||||||
|
var auctions auctiontypes.AuctionsResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &auctions)
|
||||||
|
sr.NotZero(len(auctions.Auctions.Auctions))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestQueryParamsGrpc() {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
reqUrl := fmt.Sprintf("%s/vulcanize/auction/v1beta1/params", val.APIAddress)
|
||||||
|
|
||||||
|
suite.Run("valid request to get auction params", func() {
|
||||||
|
resp, err := rest.GetRequest(reqUrl)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
var params auctiontypes.QueryParamsResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(resp, ¶ms)
|
||||||
|
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.Equal(*params.GetParams(), auctiontypes.DefaultParams())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestGetAuctionGrpc() {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
reqUrl := fmt.Sprintf("%s/vulcanize/auction/v1beta1/auctions/", val.APIAddress)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
url string
|
||||||
|
errorMsg string
|
||||||
|
isErrorExpected bool
|
||||||
|
preRun func() string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"invalid request to get an auction",
|
||||||
|
reqUrl + randomAuctionID,
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
func() string { return "" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valid request to get an auction",
|
||||||
|
reqUrl,
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
func() string { return suite.defaultAuctionID },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.msg, func() {
|
||||||
|
auctionID := tc.preRun()
|
||||||
|
resp, err := rest.GetRequest(tc.url + auctionID)
|
||||||
|
if tc.isErrorExpected {
|
||||||
|
sr.Contains(string(resp), tc.errorMsg)
|
||||||
|
} else {
|
||||||
|
sr.NoError(err)
|
||||||
|
var auction auctiontypes.AuctionResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &auction)
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.Equal(auctionID, auction.Auction.Id)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestGetBidsGrpc() {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
reqUrl := fmt.Sprintf("%s/vulcanize/auction/v1beta1/bids/", val.APIAddress)
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
url string
|
||||||
|
errorMsg string
|
||||||
|
isErrorExpected bool
|
||||||
|
preRun func() string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"invalid request to get all bids",
|
||||||
|
reqUrl,
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
func() string { return "" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valid request to get all bids",
|
||||||
|
reqUrl,
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
func() string { return suite.createAuctionAndBid(false, true) },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.msg, func() {
|
||||||
|
auctionID := tc.preRun()
|
||||||
|
tc.url += auctionID
|
||||||
|
resp, err := rest.GetRequest(tc.url)
|
||||||
|
if tc.isErrorExpected {
|
||||||
|
sr.Contains(string(resp), tc.errorMsg)
|
||||||
|
} else {
|
||||||
|
sr.NoError(err)
|
||||||
|
var bids auctiontypes.BidsResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &bids)
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.Equal(auctionID, bids.Bids[0].AuctionId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestGetBidGrpc() {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
reqUrl := fmt.Sprintf("%s/vulcanize/auction/v1beta1/bids/", val.APIAddress)
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
url string
|
||||||
|
errorMsg string
|
||||||
|
isErrorExpected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"invalid request to get bid",
|
||||||
|
fmt.Sprintf("%s/%s/", reqUrl, randomAuctionID),
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valid request to get bid",
|
||||||
|
fmt.Sprintf("%s/%s/%s", reqUrl, randomAuctionID, randomBidderAddress),
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.msg, func() {
|
||||||
|
resp, err := rest.GetRequest(tc.url)
|
||||||
|
if tc.isErrorExpected {
|
||||||
|
sr.Contains(string(resp), tc.errorMsg)
|
||||||
|
} else {
|
||||||
|
sr.NoError(err)
|
||||||
|
var bid auctiontypes.BidResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &bid)
|
||||||
|
sr.NoError(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestGetAuctionsByOwnerGrpc() {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
reqUrl := fmt.Sprintf("%s/vulcanize/auction/v1beta1/by-owner/", val.APIAddress)
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
url string
|
||||||
|
errorMsg string
|
||||||
|
isErrorExpected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"invalid request to get auctions by owner",
|
||||||
|
reqUrl,
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valid request to get auctions by owner",
|
||||||
|
fmt.Sprintf("%s/%s", reqUrl, randomOwnerAddress),
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.msg, func() {
|
||||||
|
resp, err := rest.GetRequest(tc.url)
|
||||||
|
if tc.isErrorExpected {
|
||||||
|
sr.Contains(string(resp), tc.errorMsg)
|
||||||
|
} else {
|
||||||
|
sr.NoError(err)
|
||||||
|
var auctions auctiontypes.AuctionsResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &auctions)
|
||||||
|
sr.NoError(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestQueryBalanceGrpc() {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
reqUrl := fmt.Sprintf("%s/vulcanize/auction/v1beta1/balance", val.APIAddress)
|
||||||
|
msg := "valid request to get the auction module balance"
|
||||||
|
|
||||||
|
suite.createAuctionAndBid(false, true)
|
||||||
|
|
||||||
|
suite.Run(msg, func() {
|
||||||
|
resp, err := rest.GetRequest(reqUrl)
|
||||||
|
sr.NoError(err)
|
||||||
|
|
||||||
|
var response auctiontypes.BalanceResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
|
||||||
|
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.NotZero(len(response.GetBalance()))
|
||||||
|
})
|
||||||
|
}
|
311
x/auction/client/testutil/query.go
Normal file
311
x/auction/client/testutil/query.go
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
package testutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||||
|
tmcli "github.com/tendermint/tendermint/libs/cli"
|
||||||
|
"github.com/tharsis/ethermint/x/auction/client/cli"
|
||||||
|
"github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var queryJSONFlag = []string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestGetCmdQueryParams() {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", "fetch query params"), func() {
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdQueryParams(), queryJSONFlag)
|
||||||
|
sr.NoError(err)
|
||||||
|
var params types.QueryParamsResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), ¶ms)
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.Equal(types.DefaultParams(), *params.Params)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestGetCmdBalance() {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
createAuctionAndBid bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"fetch module balance without creating auction and bid",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch module balance with valid auction and bid",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
|
if test.createAuctionAndBid {
|
||||||
|
suite.createAuctionAndBid(false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdBalance(), queryJSONFlag)
|
||||||
|
sr.NoError(err)
|
||||||
|
var balance types.BalanceResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &balance)
|
||||||
|
sr.NoError(err)
|
||||||
|
if test.createAuctionAndBid {
|
||||||
|
sr.NotZero(len(balance.Balance))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestGetCmdList() {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
createAuction bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"list auctions when no auctions exist",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"list auctions after creating an auction",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdList(), queryJSONFlag)
|
||||||
|
sr.NoError(err)
|
||||||
|
var auctions types.AuctionsResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &auctions)
|
||||||
|
sr.NoError(err)
|
||||||
|
if test.createAuction {
|
||||||
|
sr.NotZero(len(auctions.Auctions.Auctions))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestGetCmdGetBid() {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
args []string
|
||||||
|
createAuctionAndBid bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"get bid without creating auction",
|
||||||
|
[]string{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"get bid after creating auction and bid",
|
||||||
|
[]string{},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
|
if test.createAuctionAndBid {
|
||||||
|
auctionID := suite.createAuctionAndBid(false, true)
|
||||||
|
test.args = append(test.args, auctionID)
|
||||||
|
getBidsArgs := []string{auctionID, queryJSONFlag[0]}
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdGetBids(), getBidsArgs)
|
||||||
|
sr.NoError(err)
|
||||||
|
var bids types.BidsResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &bids)
|
||||||
|
sr.NoError(err)
|
||||||
|
test.args = append(test.args, bids.GetBids()[0].BidderAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
test.args = append(test.args, queryJSONFlag...)
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdGetBid(), test.args)
|
||||||
|
if test.createAuctionAndBid {
|
||||||
|
sr.NoError(err)
|
||||||
|
var bid types.BidResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &bid)
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.NotNil(bid.GetBid())
|
||||||
|
} else {
|
||||||
|
sr.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestGetCmdGetBids() {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
args []string
|
||||||
|
createAuctionAndBid bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"get bids without creating auction",
|
||||||
|
[]string{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"get bids after creating auction and bid",
|
||||||
|
[]string{},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
|
if test.createAuctionAndBid {
|
||||||
|
auctionID := suite.createAuctionAndBid(false, true)
|
||||||
|
test.args = append(test.args, auctionID)
|
||||||
|
}
|
||||||
|
|
||||||
|
test.args = append(test.args, queryJSONFlag...)
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdGetBids(), test.args)
|
||||||
|
if test.createAuctionAndBid {
|
||||||
|
sr.NoError(err)
|
||||||
|
var bids types.BidsResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &bids)
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.NotZero(len(bids.Bids))
|
||||||
|
} else {
|
||||||
|
sr.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestGetCmdGetAuction() {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
auctionID string
|
||||||
|
createAuction bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"get auction with empty auction ID",
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"get auction with valid auction ID",
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
|
if test.createAuction {
|
||||||
|
test.auctionID = suite.defaultAuctionID
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{test.auctionID, queryJSONFlag[0]}
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdGetAuction(), args)
|
||||||
|
if test.createAuction {
|
||||||
|
sr.NoError(err)
|
||||||
|
var auction types.AuctionResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &auction)
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.NotNil(auction.GetAuction())
|
||||||
|
sr.Equal(test.auctionID, auction.GetAuction().Id)
|
||||||
|
} else {
|
||||||
|
sr.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestGetCmdAuctionsByBidder() {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
createAuctionAndBid bool
|
||||||
|
bidderAddress string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"get auctions by bidder without creating auctions",
|
||||||
|
false,
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"get auctions by bidder for valid bidder address",
|
||||||
|
true,
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
|
if test.createAuctionAndBid {
|
||||||
|
auctionID := suite.createAuctionAndBid(false, true)
|
||||||
|
args := []string{auctionID, queryJSONFlag[0]}
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdGetBids(), args)
|
||||||
|
sr.NoError(err)
|
||||||
|
var bids types.BidsResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &bids)
|
||||||
|
sr.NoError(err)
|
||||||
|
test.bidderAddress = bids.Bids[0].BidderAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
getByBidderArgs := []string{test.bidderAddress, queryJSONFlag[0]}
|
||||||
|
_, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdAuctionsByBidder(), getByBidderArgs)
|
||||||
|
if test.createAuctionAndBid {
|
||||||
|
sr.NoError(err)
|
||||||
|
} else {
|
||||||
|
sr.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite IntegrationTestSuite) createAuctionAndBid(createAuction, createBid bool) string {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
auctionID := ""
|
||||||
|
|
||||||
|
if createAuction {
|
||||||
|
auctionArgs := []string{
|
||||||
|
sampleCommitTime, sampleRevealTime,
|
||||||
|
fmt.Sprintf("10%s", suite.cfg.BondDenom),
|
||||||
|
fmt.Sprintf("10%s", suite.cfg.BondDenom),
|
||||||
|
fmt.Sprintf("100%s", suite.cfg.BondDenom),
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := suite.executeTx(cli.GetCmdCreateAuction(), auctionArgs, ownerAccount)
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.Zero(resp.Code)
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdList(), queryJSONFlag)
|
||||||
|
sr.NoError(err)
|
||||||
|
var queryResponse types.AuctionsResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
|
||||||
|
sr.NoError(err)
|
||||||
|
auctionID = queryResponse.Auctions.Auctions[0].Id
|
||||||
|
} else {
|
||||||
|
auctionID = suite.defaultAuctionID
|
||||||
|
}
|
||||||
|
|
||||||
|
if createBid {
|
||||||
|
bidArgs := []string{auctionID, fmt.Sprintf("200%s", suite.cfg.BondDenom)}
|
||||||
|
resp, err := suite.executeTx(cli.GetCmdCommitBid(), bidArgs, bidderAccount)
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.Zero(resp.Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
return auctionID
|
||||||
|
}
|
141
x/auction/client/testutil/tx.go
Normal file
141
x/auction/client/testutil/tx.go
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package testutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
|
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
tmcli "github.com/tendermint/tendermint/libs/cli"
|
||||||
|
"github.com/tharsis/ethermint/x/auction/client/cli"
|
||||||
|
"github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sampleCommitTime = "90s"
|
||||||
|
sampleRevealTime = "5s"
|
||||||
|
placeholderAuctionID = "placeholder_auction_id"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestTxCreateAuction() {
|
||||||
|
sr := suite.Require()
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
args []string
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"create auction with missing arguments",
|
||||||
|
[]string{sampleCommitTime, sampleRevealTime},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create auction with proper arguments",
|
||||||
|
[]string{
|
||||||
|
sampleCommitTime, sampleRevealTime,
|
||||||
|
fmt.Sprintf("10%s", suite.cfg.BondDenom),
|
||||||
|
fmt.Sprintf("10%s", suite.cfg.BondDenom),
|
||||||
|
fmt.Sprintf("100%s", suite.cfg.BondDenom),
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
|
resp, err := suite.executeTx(cli.GetCmdCreateAuction(), test.args, ownerAccount)
|
||||||
|
if test.expectErr {
|
||||||
|
sr.Error(err)
|
||||||
|
} else {
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.Zero(resp.Code)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestTxCommitBid() {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
sr := suite.Require()
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
args []string
|
||||||
|
createAuction bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"commit bid with missing args",
|
||||||
|
[]string{fmt.Sprintf("200%s", suite.cfg.BondDenom)},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commit bid with valid args",
|
||||||
|
[]string{
|
||||||
|
placeholderAuctionID,
|
||||||
|
fmt.Sprintf("200%s", suite.cfg.BondDenom),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
|
if test.createAuction {
|
||||||
|
auctionArgs := []string{
|
||||||
|
sampleCommitTime, sampleRevealTime,
|
||||||
|
fmt.Sprintf("10%s", suite.cfg.BondDenom),
|
||||||
|
fmt.Sprintf("10%s", suite.cfg.BondDenom),
|
||||||
|
fmt.Sprintf("100%s", suite.cfg.BondDenom),
|
||||||
|
}
|
||||||
|
_, err := suite.executeTx(cli.GetCmdCreateAuction(), auctionArgs, ownerAccount)
|
||||||
|
sr.NoError(err)
|
||||||
|
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdList(),
|
||||||
|
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)})
|
||||||
|
sr.NoError(err)
|
||||||
|
var queryResponse types.AuctionsResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.NotNil(queryResponse.GetAuctions())
|
||||||
|
test.args[0] = queryResponse.GetAuctions().Auctions[0].Id
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := suite.executeTx(cli.GetCmdCommitBid(), test.args, bidderAccount)
|
||||||
|
if test.createAuction {
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.Zero(resp.Code)
|
||||||
|
} else {
|
||||||
|
sr.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) executeTx(cmd *cobra.Command, args []string, caller string) (sdk.TxResponse, error) {
|
||||||
|
val := suite.network.Validators[0]
|
||||||
|
additionalArgs := []string{
|
||||||
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, caller),
|
||||||
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||||
|
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||||
|
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", suite.cfg.BondDenom)),
|
||||||
|
}
|
||||||
|
args = append(args, additionalArgs...)
|
||||||
|
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, args)
|
||||||
|
if err != nil {
|
||||||
|
return sdk.TxResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp sdk.TxResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp)
|
||||||
|
if err != nil {
|
||||||
|
return sdk.TxResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = suite.network.WaitForNextBlock()
|
||||||
|
if err != nil {
|
||||||
|
return sdk.TxResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
44
x/auction/genesis.go
Normal file
44
x/auction/genesis.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package auction
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
|
||||||
|
"github.com/tharsis/ethermint/x/auction/keeper"
|
||||||
|
"github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// func NewGenesisState(params types.Params, auctions []types.Auction) types.GenesisState {
|
||||||
|
// return types.GenesisState{Params: params, Auctions: &types.Auctions{Auctions: auctions}}
|
||||||
|
// }
|
||||||
|
|
||||||
|
func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, data types.GenesisState) []abci.ValidatorUpdate {
|
||||||
|
keeper.SetParams(ctx, data.Params)
|
||||||
|
|
||||||
|
for _, auction := range data.Auctions {
|
||||||
|
keeper.SaveAuction(ctx, auction)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []abci.ValidatorUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) types.GenesisState {
|
||||||
|
params := keeper.GetParams(ctx)
|
||||||
|
auctions := keeper.ListAuctions(ctx)
|
||||||
|
|
||||||
|
var genesisAuctions []*types.Auction
|
||||||
|
for _, auction := range auctions {
|
||||||
|
genesisAuctions = append(genesisAuctions, &auction)
|
||||||
|
}
|
||||||
|
return types.GenesisState{Params: params, Auctions: genesisAuctions}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateGenesis(data types.GenesisState) error {
|
||||||
|
err := data.Params.Validate()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
91
x/auction/keeper/grpc_query.go
Normal file
91
x/auction/keeper/grpc_query.go
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package keeper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
|
||||||
|
"github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Querier struct {
|
||||||
|
Keeper
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ types.QueryServer = Querier{}
|
||||||
|
|
||||||
|
// Auctions queries all auctions
|
||||||
|
func (q Querier) Auctions(c context.Context, req *types.AuctionsRequest) (*types.AuctionsResponse, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(c)
|
||||||
|
resp := q.Keeper.ListAuctions(ctx)
|
||||||
|
return &types.AuctionsResponse{Auctions: &types.Auctions{Auctions: resp}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAuction queries an auction
|
||||||
|
func (q Querier) GetAuction(c context.Context, req *types.AuctionRequest) (*types.AuctionResponse, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(c)
|
||||||
|
if req.Id == "" {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "auction ID is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := q.Keeper.GetAuction(ctx, req.Id)
|
||||||
|
return &types.AuctionResponse{Auction: resp}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBid queries and auction bid
|
||||||
|
func (q Querier) GetBid(c context.Context, req *types.BidRequest) (*types.BidResponse, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(c)
|
||||||
|
if req.AuctionId == "" {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "auction ID is required")
|
||||||
|
}
|
||||||
|
if req.Bidder == "" {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "bidder address is required")
|
||||||
|
}
|
||||||
|
resp := q.Keeper.GetBid(ctx, req.AuctionId, req.Bidder)
|
||||||
|
return &types.BidResponse{Bid: &resp}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBids queries all auction bids
|
||||||
|
func (q Querier) GetBids(c context.Context, req *types.BidsRequest) (*types.BidsResponse, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(c)
|
||||||
|
if req.AuctionId == "" {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "auction ID is required")
|
||||||
|
}
|
||||||
|
resp := q.Keeper.GetBids(ctx, req.AuctionId)
|
||||||
|
return &types.BidsResponse{Bids: resp}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuctionsByBidder queries auctions by bidder
|
||||||
|
func (q Querier) AuctionsByBidder(c context.Context, req *types.AuctionsByBidderRequest) (*types.AuctionsByBidderResponse, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(c)
|
||||||
|
if req.BidderAddress == "" {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "bidder address is required")
|
||||||
|
}
|
||||||
|
resp := q.Keeper.QueryAuctionsByBidder(ctx, req.BidderAddress)
|
||||||
|
return &types.AuctionsByBidderResponse{Auctions: &types.Auctions{Auctions: resp}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuctionsByOwner queries auctions by owner
|
||||||
|
func (q Querier) AuctionsByOwner(c context.Context, req *types.AuctionsByOwnerRequest) (*types.AuctionsByOwnerResponse, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(c)
|
||||||
|
if req.OwnerAddress == "" {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "owner address is required")
|
||||||
|
}
|
||||||
|
resp := q.Keeper.QueryAuctionsByOwner(ctx, req.OwnerAddress)
|
||||||
|
return &types.AuctionsByOwnerResponse{Auctions: &types.Auctions{Auctions: resp}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryParams implements the params query command
|
||||||
|
func (q Querier) QueryParams(c context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(c)
|
||||||
|
resp := q.Keeper.GetParams(ctx)
|
||||||
|
return &types.QueryParamsResponse{Params: &resp}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Balance queries the auction module account balance
|
||||||
|
func (q Querier) Balance(c context.Context, req *types.BalanceRequest) (*types.BalanceResponse, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(c)
|
||||||
|
resp := q.Keeper.GetAuctionModuleBalances(ctx)
|
||||||
|
return &types.BalanceResponse{Balance: resp}, nil
|
||||||
|
}
|
355
x/auction/keeper/grpc_query_test.go
Normal file
355
x/auction/keeper/grpc_query_test.go
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
package keeper_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/tharsis/ethermint/app"
|
||||||
|
"github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const testCommitHash = "71D8CF34026E32A3A34C2C2D4ADF25ABC8D7943A4619761BE27F196603D91B9D"
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestGrpcGetAllAuctions() {
|
||||||
|
client, ctx, k := suite.queryClient, suite.ctx, suite.app.AuctionKeeper
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
req *types.AuctionsRequest
|
||||||
|
createAuctions bool
|
||||||
|
auctionCount int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"fetch auctions when no auctions exist",
|
||||||
|
&types.AuctionsRequest{},
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"fetch auctions with one auction created",
|
||||||
|
&types.AuctionsRequest{},
|
||||||
|
true,
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
|
if test.createAuctions {
|
||||||
|
account := app.CreateRandomAccounts(1)[0]
|
||||||
|
err := simapp.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(
|
||||||
|
sdk.Coin{Amount: sdk.NewInt(100), Denom: sdk.DefaultBondDenom},
|
||||||
|
))
|
||||||
|
|
||||||
|
_, err = k.CreateAuction(ctx, types.NewMsgCreateAuction(k.GetParams(ctx), account))
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, _ := client.Auctions(context.Background(), test.req)
|
||||||
|
suite.Require().Equal(test.auctionCount, len(resp.GetAuctions().Auctions))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestGrpcQueryParams() {
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
req *types.QueryParamsRequest
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"fetch params",
|
||||||
|
&types.QueryParamsRequest{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
|
resp, err := suite.queryClient.QueryParams(context.Background(), test.req)
|
||||||
|
suite.Require().Nil(err)
|
||||||
|
suite.Require().Equal(*(resp.Params), types.DefaultParams())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestGrpcGetAuction() {
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
req *types.AuctionRequest
|
||||||
|
createAuction bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"fetch auction with empty auction ID",
|
||||||
|
&types.AuctionRequest{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch auction with valid auction ID",
|
||||||
|
&types.AuctionRequest{},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
|
if test.createAuction {
|
||||||
|
auction, _, err := suite.createAuctionAndCommitBid(false)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
test.req.Id = auction.Id
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := suite.queryClient.GetAuction(context.Background(), test.req)
|
||||||
|
if test.createAuction {
|
||||||
|
suite.Require().Nil(err)
|
||||||
|
suite.Require().NotNil(resp.GetAuction())
|
||||||
|
suite.Require().Equal(test.req.Id, resp.GetAuction().Id)
|
||||||
|
} else {
|
||||||
|
suite.Require().NotNil(err)
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestGrpcGetBids() {
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
req *types.BidsRequest
|
||||||
|
createAuction bool
|
||||||
|
commitBid bool
|
||||||
|
bidCount int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"fetch all bids when no auction exists",
|
||||||
|
&types.BidsRequest{},
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch all bids for valid auction but no added bids",
|
||||||
|
&types.BidsRequest{},
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch all bids for valid auction and valid bid",
|
||||||
|
&types.BidsRequest{},
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
|
if test.createAuction {
|
||||||
|
auction, _, err := suite.createAuctionAndCommitBid(test.commitBid)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
test.req.AuctionId = auction.Id
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := suite.queryClient.GetBids(context.Background(), test.req)
|
||||||
|
if test.createAuction {
|
||||||
|
suite.Require().Nil(err)
|
||||||
|
suite.Require().Equal(test.bidCount, len(resp.GetBids()))
|
||||||
|
} else {
|
||||||
|
suite.Require().NotNil(err)
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestGrpcGetBid() {
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
req *types.BidRequest
|
||||||
|
createAuctionAndBid bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"fetch bid when bid does not exist",
|
||||||
|
&types.BidRequest{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch bid when valid bid exists",
|
||||||
|
&types.BidRequest{},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
|
if test.createAuctionAndBid {
|
||||||
|
auction, bid, err := suite.createAuctionAndCommitBid(test.createAuctionAndBid)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
test.req.AuctionId = auction.Id
|
||||||
|
test.req.Bidder = bid.BidderAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := suite.queryClient.GetBid(context.Background(), test.req)
|
||||||
|
if test.createAuctionAndBid {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Require().NotNil(resp.Bid)
|
||||||
|
suite.Require().Equal(test.req.Bidder, resp.Bid.BidderAddress)
|
||||||
|
} else {
|
||||||
|
suite.Require().NotNil(err)
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestGrpcGetAuctionsByBidder() {
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
req *types.AuctionsByBidderRequest
|
||||||
|
createAuctionAndCommitBid bool
|
||||||
|
auctionCount int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"get auctions by bidder with invalid bidder address",
|
||||||
|
&types.AuctionsByBidderRequest{},
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"get auctions by bidder with valid auction and bid",
|
||||||
|
&types.AuctionsByBidderRequest{},
|
||||||
|
true,
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
|
if test.createAuctionAndCommitBid {
|
||||||
|
_, bid, err := suite.createAuctionAndCommitBid(test.createAuctionAndCommitBid)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
test.req.BidderAddress = bid.BidderAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := suite.queryClient.AuctionsByBidder(context.Background(), test.req)
|
||||||
|
if test.createAuctionAndCommitBid {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Require().NotNil(resp.Auctions)
|
||||||
|
suite.Require().Equal(test.auctionCount, len(resp.Auctions.Auctions))
|
||||||
|
} else {
|
||||||
|
suite.Require().NotNil(err)
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestGrpcGetAuctionsByOwner() {
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
req *types.AuctionsByOwnerRequest
|
||||||
|
createAuction bool
|
||||||
|
auctionCount int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"get auctions by owner with invalid owner address",
|
||||||
|
&types.AuctionsByOwnerRequest{},
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"get auctions by owner with valid auction",
|
||||||
|
&types.AuctionsByOwnerRequest{},
|
||||||
|
true,
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
|
if test.createAuction {
|
||||||
|
auction, _, err := suite.createAuctionAndCommitBid(false)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
test.req.OwnerAddress = auction.OwnerAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := suite.queryClient.AuctionsByOwner(context.Background(), test.req)
|
||||||
|
if test.createAuction {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Require().NotNil(resp.Auctions)
|
||||||
|
suite.Require().Equal(test.auctionCount, len(resp.Auctions.Auctions))
|
||||||
|
} else {
|
||||||
|
suite.Require().NotNil(err)
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite KeeperTestSuite) TestGrpcQueryBalance() {
|
||||||
|
testCases := []struct {
|
||||||
|
msg string
|
||||||
|
req *types.BalanceRequest
|
||||||
|
createAuction bool
|
||||||
|
auctionCount int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"get balance with no auctions created",
|
||||||
|
&types.BalanceRequest{},
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"get balance with single auction created",
|
||||||
|
&types.BalanceRequest{},
|
||||||
|
true,
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
if test.createAuction {
|
||||||
|
_, _, err := suite.createAuctionAndCommitBid(true)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := suite.queryClient.Balance(context.Background(), test.req)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Require().Equal(test.auctionCount, len(resp.GetBalance()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) createAuctionAndCommitBid(commitBid bool) (*types.Auction, *types.Bid, error) {
|
||||||
|
ctx, k := suite.ctx, suite.app.AuctionKeeper
|
||||||
|
accCount := 1
|
||||||
|
if commitBid {
|
||||||
|
accCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
accounts := app.CreateRandomAccounts(accCount)
|
||||||
|
for _, account := range accounts {
|
||||||
|
err := simapp.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(
|
||||||
|
sdk.Coin{Amount: sdk.NewInt(100), Denom: sdk.DefaultBondDenom},
|
||||||
|
))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auction, err := k.CreateAuction(ctx, types.NewMsgCreateAuction(k.GetParams(ctx), accounts[0]))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if commitBid {
|
||||||
|
bid, err := k.CommitBid(ctx, types.NewMsgCommitBid(auction.Id, testCommitHash, accounts[1]))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return auction, bid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return auction, nil, nil
|
||||||
|
}
|
37
x/auction/keeper/invariants.go
Normal file
37
x/auction/keeper/invariants.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package keeper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
|
||||||
|
"github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RegisterInvariants registers all auction module invariants.
|
||||||
|
func RegisterInvariants(ir sdk.InvariantRegistry, k Keeper) {
|
||||||
|
ir.RegisterRoute(types.ModuleName, "module-account", ModuleAccountInvariant(k))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModuleAccountInvariant checks that the 'auction' module account balance is non-negative.
|
||||||
|
func ModuleAccountInvariant(k Keeper) sdk.Invariant {
|
||||||
|
return func(ctx sdk.Context) (string, bool) {
|
||||||
|
moduleAddress := k.accountKeeper.GetModuleAddress(types.ModuleName)
|
||||||
|
if k.bankKeeper.GetAllBalances(ctx, moduleAddress).IsAnyNegative() {
|
||||||
|
return sdk.FormatInvariant(
|
||||||
|
types.ModuleName,
|
||||||
|
"module-account",
|
||||||
|
fmt.Sprintf("Module account '%s' has negative balance.", types.ModuleName)),
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllInvariants runs all invariants of the auctions module.
|
||||||
|
func AllInvariants(k Keeper) sdk.Invariant {
|
||||||
|
return func(ctx sdk.Context) (string, bool) {
|
||||||
|
return ModuleAccountInvariant(k)(ctx)
|
||||||
|
}
|
||||||
|
}
|
658
x/auction/keeper/keeper.go
Normal file
658
x/auction/keeper/keeper.go
Normal file
@ -0,0 +1,658 @@
|
|||||||
|
package keeper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
auth "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||||
|
bank "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
||||||
|
params "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||||
|
|
||||||
|
"github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
|
||||||
|
wnsUtils "github.com/tharsis/ethermint/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CompletedAuctionDeleteTimeout => Completed auctions are deleted after this timeout (after reveals end time).
|
||||||
|
const CompletedAuctionDeleteTimeout = time.Hour * 24
|
||||||
|
|
||||||
|
// PrefixIDToAuctionIndex is the prefix for Id -> Auction index in the KVStore.
|
||||||
|
// Note: This is the primary index in the system.
|
||||||
|
// Note: Golang doesn't support const arrays.
|
||||||
|
var PrefixIDToAuctionIndex = []byte{0x00}
|
||||||
|
|
||||||
|
// prefixOwnerToAuctionsIndex is the prefix for the Owner -> [Auction] index in the KVStore.
|
||||||
|
var prefixOwnerToAuctionsIndex = []byte{0x01}
|
||||||
|
|
||||||
|
// PrefixAuctionBidsIndex is the prefix for the (auction, bidder) -> Bid index in the KVStore.
|
||||||
|
var PrefixAuctionBidsIndex = []byte{0x02}
|
||||||
|
|
||||||
|
// PrefixBidderToAuctionsIndex is the prefix for the Bidder -> [Auction] index in the KVStore.
|
||||||
|
var PrefixBidderToAuctionsIndex = []byte{0x03}
|
||||||
|
|
||||||
|
// Keeper maintains the link to storage and exposes getter/setter methods for the various parts of the state machine
|
||||||
|
type Keeper struct {
|
||||||
|
accountKeeper auth.AccountKeeper
|
||||||
|
bankKeeper bank.Keeper
|
||||||
|
|
||||||
|
// Track auction usage in other cosmos-sdk modules (more like a usage tracker).
|
||||||
|
usageKeepers []types.AuctionUsageKeeper
|
||||||
|
|
||||||
|
storeKey sdk.StoreKey // Unexposed key to access store from sdk.Context
|
||||||
|
|
||||||
|
cdc codec.BinaryCodec // The wire codec for binary encoding/decoding.
|
||||||
|
|
||||||
|
paramSubspace params.Subspace
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuctionClientKeeper is the subset of functionality exposed to other modules.
|
||||||
|
type AuctionClientKeeper interface {
|
||||||
|
HasAuction(ctx sdk.Context, id string) bool
|
||||||
|
GetAuction(ctx sdk.Context, id string) types.Auction
|
||||||
|
MatchAuctions(ctx sdk.Context, matchFn func(*types.Auction) bool) []*types.Auction
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewKeeper creates new instances of the auction Keeper
|
||||||
|
func NewKeeper(accountKeeper auth.AccountKeeper, bankKeeper bank.Keeper, storeKey sdk.StoreKey, cdc codec.BinaryCodec, ps params.Subspace) Keeper {
|
||||||
|
if !ps.HasKeyTable() {
|
||||||
|
ps = ps.WithKeyTable(types.ParamKeyTable())
|
||||||
|
}
|
||||||
|
|
||||||
|
return Keeper{
|
||||||
|
accountKeeper: accountKeeper,
|
||||||
|
bankKeeper: bankKeeper,
|
||||||
|
storeKey: storeKey,
|
||||||
|
cdc: cdc,
|
||||||
|
paramSubspace: ps,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Keeper) SetUsageKeepers(usageKeepers []types.AuctionUsageKeeper) {
|
||||||
|
k.usageKeepers = usageKeepers
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) GetUsageKeepers() []types.AuctionUsageKeeper {
|
||||||
|
return k.usageKeepers
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates Auction Id -> Auction index key.
|
||||||
|
func GetAuctionIndexKey(id string) []byte {
|
||||||
|
return append(PrefixIDToAuctionIndex, []byte(id)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates Owner -> Auctions index key.
|
||||||
|
func GetOwnerToAuctionsIndexKey(owner string, auctionID string) []byte {
|
||||||
|
return append(append(prefixOwnerToAuctionsIndex, []byte(owner)...), []byte(auctionID)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBidderToAuctionsIndexKey(bidder string, auctionID string) []byte {
|
||||||
|
return append(append(PrefixBidderToAuctionsIndex, []byte(bidder)...), []byte(auctionID)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBidIndexKey(auctionID string, bidder string) []byte {
|
||||||
|
return append(GetAuctionBidsIndexPrefix(auctionID), []byte(bidder)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAuctionBidsIndexPrefix(auctionID string) []byte {
|
||||||
|
return append(append(PrefixAuctionBidsIndex, []byte(auctionID)...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveAuction - saves a auction to the store.
|
||||||
|
func (k Keeper) SaveAuction(ctx sdk.Context, auction *types.Auction) {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
|
||||||
|
// Auction Id -> Auction index.
|
||||||
|
store.Set(GetAuctionIndexKey(auction.Id), k.cdc.MustMarshal(auction))
|
||||||
|
|
||||||
|
// Owner -> [Auction] index.
|
||||||
|
store.Set(GetOwnerToAuctionsIndexKey(auction.OwnerAddress, auction.Id), []byte{})
|
||||||
|
|
||||||
|
// Notify interested parties.
|
||||||
|
for _, keeper := range k.usageKeepers {
|
||||||
|
keeper.OnAuction(ctx, auction.Id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) SaveBid(ctx sdk.Context, bid *types.Bid) {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
store.Set(GetBidIndexKey(bid.AuctionId, bid.BidderAddress), k.cdc.MustMarshal(bid))
|
||||||
|
store.Set(GetBidderToAuctionsIndexKey(bid.BidderAddress, bid.AuctionId), []byte{})
|
||||||
|
|
||||||
|
// Notify interested parties.
|
||||||
|
for _, keeper := range k.usageKeepers {
|
||||||
|
keeper.OnAuctionBid(ctx, bid.AuctionId, bid.BidderAddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) DeleteBid(ctx sdk.Context, bid types.Bid) {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
store.Delete(GetBidIndexKey(bid.AuctionId, bid.BidderAddress))
|
||||||
|
store.Delete(GetOwnerToAuctionsIndexKey(bid.BidderAddress, bid.AuctionId))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasAuction - checks if a auction by the given Id exists.
|
||||||
|
func (k Keeper) HasAuction(ctx sdk.Context, id string) bool {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
return store.Has(GetAuctionIndexKey(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) HasBid(ctx sdk.Context, id string, bidder string) bool {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
return store.Has(GetBidIndexKey(id, bidder))
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteAuction - deletes the auction.
|
||||||
|
func (k Keeper) DeleteAuction(ctx sdk.Context, auction types.Auction) {
|
||||||
|
// Delete all bids first.
|
||||||
|
bids := k.GetBids(ctx, auction.Id)
|
||||||
|
for _, bid := range bids {
|
||||||
|
k.DeleteBid(ctx, *bid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the auction itself.
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
store.Delete(GetAuctionIndexKey(auction.Id))
|
||||||
|
store.Delete(GetOwnerToAuctionsIndexKey(auction.OwnerAddress, auction.Id))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAuction - gets a record from the store.
|
||||||
|
func (k Keeper) GetAuction(ctx sdk.Context, id string) *types.Auction {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
auctionKey := GetAuctionIndexKey(id)
|
||||||
|
if !store.Has(auctionKey) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
bz := store.Get(auctionKey)
|
||||||
|
var obj types.Auction
|
||||||
|
k.cdc.MustUnmarshal(bz, &obj)
|
||||||
|
|
||||||
|
return &obj
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBids gets the auction bids.
|
||||||
|
func (k Keeper) GetBids(ctx sdk.Context, id string) []*types.Bid {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
bids := []*types.Bid{}
|
||||||
|
itr := sdk.KVStorePrefixIterator(store, GetAuctionBidsIndexPrefix(id))
|
||||||
|
defer itr.Close()
|
||||||
|
for ; itr.Valid(); itr.Next() {
|
||||||
|
bz := store.Get(itr.Key())
|
||||||
|
if bz != nil {
|
||||||
|
var obj types.Bid
|
||||||
|
k.cdc.MustUnmarshal(bz, &obj)
|
||||||
|
bids = append(bids, &obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bids
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) GetBid(ctx sdk.Context, id string, bidder string) types.Bid {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
|
||||||
|
bz := store.Get(GetBidIndexKey(id, bidder))
|
||||||
|
var obj types.Bid
|
||||||
|
k.cdc.MustUnmarshal(bz, &obj)
|
||||||
|
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAuctions - get all auctions.
|
||||||
|
func (k Keeper) ListAuctions(ctx sdk.Context) []types.Auction {
|
||||||
|
var auctions []types.Auction
|
||||||
|
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
itr := sdk.KVStorePrefixIterator(store, PrefixIDToAuctionIndex)
|
||||||
|
defer itr.Close()
|
||||||
|
for ; itr.Valid(); itr.Next() {
|
||||||
|
bz := store.Get(itr.Key())
|
||||||
|
if bz != nil {
|
||||||
|
var obj types.Auction
|
||||||
|
k.cdc.MustUnmarshal(bz, &obj)
|
||||||
|
auctions = append(auctions, obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return auctions
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryAuctionsByOwner - query auctions by owner.
|
||||||
|
func (k Keeper) QueryAuctionsByOwner(ctx sdk.Context, ownerAddress string) []types.Auction {
|
||||||
|
auctions := []types.Auction{}
|
||||||
|
|
||||||
|
ownerPrefix := append(prefixOwnerToAuctionsIndex, []byte(ownerAddress)...)
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
itr := sdk.KVStorePrefixIterator(store, ownerPrefix)
|
||||||
|
defer itr.Close()
|
||||||
|
for ; itr.Valid(); itr.Next() {
|
||||||
|
auctionID := itr.Key()[len(ownerPrefix):]
|
||||||
|
bz := store.Get(append(PrefixIDToAuctionIndex, auctionID...))
|
||||||
|
if bz != nil {
|
||||||
|
var obj types.Auction
|
||||||
|
k.cdc.MustUnmarshal(bz, &obj)
|
||||||
|
auctions = append(auctions, obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return auctions
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryAuctionsByBidder - query auctions by bidder
|
||||||
|
func (k Keeper) QueryAuctionsByBidder(ctx sdk.Context, bidderAddress string) []types.Auction {
|
||||||
|
auctions := []types.Auction{}
|
||||||
|
|
||||||
|
bidderPrefix := append(PrefixBidderToAuctionsIndex, []byte(bidderAddress)...)
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
itr := sdk.KVStorePrefixIterator(store, []byte(bidderPrefix))
|
||||||
|
defer itr.Close()
|
||||||
|
for ; itr.Valid(); itr.Next() {
|
||||||
|
auctionID := itr.Key()[len(bidderPrefix):]
|
||||||
|
bz := store.Get(append(PrefixIDToAuctionIndex, auctionID...))
|
||||||
|
if bz != nil {
|
||||||
|
var obj types.Auction
|
||||||
|
k.cdc.MustUnmarshal(bz, &obj)
|
||||||
|
auctions = append(auctions, obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return auctions
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchAuctions - get all matching auctions.
|
||||||
|
func (k Keeper) MatchAuctions(ctx sdk.Context, matchFn func(*types.Auction) bool) []*types.Auction {
|
||||||
|
var auctions []*types.Auction
|
||||||
|
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
itr := sdk.KVStorePrefixIterator(store, PrefixIDToAuctionIndex)
|
||||||
|
defer itr.Close()
|
||||||
|
for ; itr.Valid(); itr.Next() {
|
||||||
|
bz := store.Get(itr.Key())
|
||||||
|
if bz != nil {
|
||||||
|
var obj types.Auction
|
||||||
|
k.cdc.MustUnmarshal(bz, &obj)
|
||||||
|
if matchFn(&obj) {
|
||||||
|
auctions = append(auctions, &obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return auctions
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateAuction creates a new auction.
|
||||||
|
func (k Keeper) CreateAuction(ctx sdk.Context, msg types.MsgCreateAuction) (*types.Auction, error) {
|
||||||
|
// Might be called from another module directly, always validate.
|
||||||
|
err := msg.ValidateBasic()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate auction Id.
|
||||||
|
account := k.accountKeeper.GetAccount(ctx, signerAddress)
|
||||||
|
if account == nil {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "Account not found.")
|
||||||
|
}
|
||||||
|
|
||||||
|
auctionID := types.AuctionID{
|
||||||
|
Address: signerAddress,
|
||||||
|
AccNum: account.GetAccountNumber(),
|
||||||
|
Sequence: account.GetSequence(),
|
||||||
|
}.Generate()
|
||||||
|
|
||||||
|
// Compute timestamps.
|
||||||
|
now := ctx.BlockTime()
|
||||||
|
commitsEndTime := now.Add(time.Duration(msg.CommitsDuration))
|
||||||
|
revealsEndTime := now.Add(time.Duration(msg.CommitsDuration + msg.RevealsDuration))
|
||||||
|
|
||||||
|
auction := types.Auction{
|
||||||
|
Id: auctionID,
|
||||||
|
Status: types.AuctionStatusCommitPhase,
|
||||||
|
OwnerAddress: signerAddress.String(),
|
||||||
|
CreateTime: now,
|
||||||
|
CommitsEndTime: commitsEndTime,
|
||||||
|
RevealsEndTime: revealsEndTime,
|
||||||
|
CommitFee: msg.CommitFee,
|
||||||
|
RevealFee: msg.RevealFee,
|
||||||
|
MinimumBid: msg.MinimumBid,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save auction in store.
|
||||||
|
k.SaveAuction(ctx, &auction)
|
||||||
|
|
||||||
|
return &auction, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) CommitBid(ctx sdk.Context, msg types.MsgCommitBid) (*types.Bid, error) {
|
||||||
|
if !k.HasAuction(ctx, msg.AuctionId) {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Auction not found.")
|
||||||
|
}
|
||||||
|
|
||||||
|
auction := k.GetAuction(ctx, msg.AuctionId)
|
||||||
|
if auction.Status != types.AuctionStatusCommitPhase {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Auction is not in commit phase.")
|
||||||
|
}
|
||||||
|
|
||||||
|
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take auction fees from account.
|
||||||
|
totalFee := auction.CommitFee.Add(auction.RevealFee)
|
||||||
|
sdkErr := k.bankKeeper.SendCoinsFromAccountToModule(ctx, signerAddress, types.ModuleName, sdk.NewCoins(totalFee))
|
||||||
|
if sdkErr != nil {
|
||||||
|
return nil, sdkErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if an old bid already exists, if so, return old bids auction fee (update bid scenario).
|
||||||
|
bidder := signerAddress.String()
|
||||||
|
if k.HasBid(ctx, msg.AuctionId, bidder) {
|
||||||
|
oldBid := k.GetBid(ctx, msg.AuctionId, bidder)
|
||||||
|
oldTotalFee := oldBid.CommitFee.Add(oldBid.RevealFee)
|
||||||
|
sdkErr := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, signerAddress, sdk.NewCoins(oldTotalFee))
|
||||||
|
if sdkErr != nil {
|
||||||
|
return nil, sdkErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save new bid.
|
||||||
|
bid := types.Bid{
|
||||||
|
AuctionId: msg.AuctionId,
|
||||||
|
BidderAddress: bidder,
|
||||||
|
Status: types.BidStatusCommitted,
|
||||||
|
CommitHash: msg.CommitHash,
|
||||||
|
CommitTime: ctx.BlockTime(),
|
||||||
|
CommitFee: auction.CommitFee,
|
||||||
|
RevealFee: auction.RevealFee,
|
||||||
|
}
|
||||||
|
|
||||||
|
k.SaveBid(ctx, &bid)
|
||||||
|
|
||||||
|
return &bid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RevealBid reeals a bid comitted earlier.
|
||||||
|
func (k Keeper) RevealBid(ctx sdk.Context, msg types.MsgRevealBid) (*types.Auction, error) {
|
||||||
|
if !k.HasAuction(ctx, msg.AuctionId) {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Auction not found.")
|
||||||
|
}
|
||||||
|
|
||||||
|
auction := k.GetAuction(ctx, msg.AuctionId)
|
||||||
|
if auction.Status != types.AuctionStatusRevealPhase {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Auction is not in reveal phase.")
|
||||||
|
}
|
||||||
|
|
||||||
|
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !k.HasBid(ctx, msg.AuctionId, signerAddress.String()) {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Bid not found.")
|
||||||
|
}
|
||||||
|
|
||||||
|
bid := k.GetBid(ctx, auction.Id, signerAddress.String())
|
||||||
|
if bid.Status != types.BidStatusCommitted {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Bid not in committed state.")
|
||||||
|
}
|
||||||
|
|
||||||
|
revealBytes, err := hex.DecodeString(msg.Reveal)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal string.")
|
||||||
|
}
|
||||||
|
|
||||||
|
cid, err := wnsUtils.CIDFromJSONBytes(revealBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal JSON.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if bid.CommitHash != cid {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Commit hash mismatch.")
|
||||||
|
}
|
||||||
|
|
||||||
|
var reveal map[string]interface{}
|
||||||
|
err = json.Unmarshal(revealBytes, &reveal)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Reveal JSON unmarshal error.")
|
||||||
|
}
|
||||||
|
|
||||||
|
chainID, err := wnsUtils.GetAttributeAsString(reveal, "chainId")
|
||||||
|
if err != nil || chainID != ctx.ChainID() {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal chainID.")
|
||||||
|
}
|
||||||
|
|
||||||
|
auctionID, err := wnsUtils.GetAttributeAsString(reveal, "auctionId")
|
||||||
|
if err != nil || auctionID != msg.AuctionId {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal auction Id.")
|
||||||
|
}
|
||||||
|
|
||||||
|
bidderAddress, err := wnsUtils.GetAttributeAsString(reveal, "bidderAddress")
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal bid address.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if bidderAddress != signerAddress.String() {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Reveal bid address mismatch.")
|
||||||
|
}
|
||||||
|
|
||||||
|
bidAmountStr, err := wnsUtils.GetAttributeAsString(reveal, "bidAmount")
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal bid amount.")
|
||||||
|
}
|
||||||
|
|
||||||
|
bidAmount, err := sdk.ParseCoinNormalized(bidAmountStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal bid amount.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if bidAmount.IsLT(auction.MinimumBid) {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Bid is lower than minimum bid.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock bid amount.
|
||||||
|
sdkErr := k.bankKeeper.SendCoinsFromAccountToModule(ctx, signerAddress, types.ModuleName, sdk.NewCoins(bidAmount))
|
||||||
|
if sdkErr != nil {
|
||||||
|
return nil, sdkErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update bid.
|
||||||
|
bid.BidAmount = bidAmount
|
||||||
|
bid.RevealTime = ctx.BlockTime()
|
||||||
|
bid.Status = types.BidStatusRevealed
|
||||||
|
k.SaveBid(ctx, &bid)
|
||||||
|
|
||||||
|
return auction, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAuctionModuleBalances gets the auction module account(s) balances.
|
||||||
|
func (k Keeper) GetAuctionModuleBalances(ctx sdk.Context) sdk.Coins {
|
||||||
|
moduleAddress := k.accountKeeper.GetModuleAddress(types.ModuleName)
|
||||||
|
balances := k.bankKeeper.GetAllBalances(ctx, moduleAddress)
|
||||||
|
return balances
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) EndBlockerProcessAuctions(ctx sdk.Context) {
|
||||||
|
// Transition auction state (commit, reveal, expired, completed).
|
||||||
|
k.processAuctionPhases(ctx)
|
||||||
|
|
||||||
|
// Delete stale auctions.
|
||||||
|
k.deleteCompletedAuctions(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) processAuctionPhases(ctx sdk.Context) {
|
||||||
|
auctions := k.MatchAuctions(ctx, func(_ *types.Auction) bool {
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, auction := range auctions {
|
||||||
|
// Commit -> Reveal state.
|
||||||
|
if auction.Status == types.AuctionStatusCommitPhase && ctx.BlockTime().After(auction.CommitsEndTime) {
|
||||||
|
auction.Status = types.AuctionStatusRevealPhase
|
||||||
|
k.SaveAuction(ctx, auction)
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Moved auction %s to reveal phase.", auction.Id))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reveal -> Expired state.
|
||||||
|
if auction.Status == types.AuctionStatusRevealPhase && ctx.BlockTime().After(auction.RevealsEndTime) {
|
||||||
|
auction.Status = types.AuctionStatusExpired
|
||||||
|
k.SaveAuction(ctx, auction)
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Moved auction %s to expired state.", auction.Id))
|
||||||
|
}
|
||||||
|
|
||||||
|
// If auction has expired, pick a winner from revealed bids.
|
||||||
|
if auction.Status == types.AuctionStatusExpired {
|
||||||
|
k.pickAuctionWinner(ctx, auction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete completed stale auctions.
|
||||||
|
func (k Keeper) deleteCompletedAuctions(ctx sdk.Context) {
|
||||||
|
auctions := k.MatchAuctions(ctx, func(auction *types.Auction) bool {
|
||||||
|
deleteTime := auction.RevealsEndTime.Add(CompletedAuctionDeleteTimeout)
|
||||||
|
return auction.Status == types.AuctionStatusCompleted && ctx.BlockTime().After(deleteTime)
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, auction := range auctions {
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Deleting completed auction %s after timeout.", auction.Id))
|
||||||
|
k.DeleteAuction(ctx, *auction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) pickAuctionWinner(ctx sdk.Context, auction *types.Auction) {
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Picking auction %s winner.", auction.Id))
|
||||||
|
|
||||||
|
var highestBid *types.Bid
|
||||||
|
var secondHighestBid *types.Bid
|
||||||
|
|
||||||
|
bids := k.GetBids(ctx, auction.Id)
|
||||||
|
for _, bid := range bids {
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Processing bid %s %s", bid.BidderAddress, bid.BidAmount.String()))
|
||||||
|
|
||||||
|
// Only consider revealed bids.
|
||||||
|
if bid.Status != types.BidStatusRevealed {
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Ignoring unrevealed bid %s %s", bid.BidderAddress, bid.BidAmount.String()))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init highest bid.
|
||||||
|
if highestBid == nil {
|
||||||
|
highestBid = bid
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Initializing 1st bid %s %s", bid.BidderAddress, bid.BidAmount.String()))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if highestBid.BidAmount.IsLT(bid.BidAmount) {
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("New highest bid %s %s", bid.BidderAddress, bid.BidAmount.String()))
|
||||||
|
|
||||||
|
secondHighestBid = highestBid
|
||||||
|
highestBid = bid
|
||||||
|
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Updated 1st bid %s %s", highestBid.BidderAddress, highestBid.BidAmount.String()))
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Updated 2nd bid %s %s", secondHighestBid.BidderAddress, secondHighestBid.BidAmount.String()))
|
||||||
|
|
||||||
|
} else if secondHighestBid == nil || secondHighestBid.BidAmount.IsLT(bid.BidAmount) {
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("New 2nd highest bid %s %s", bid.BidderAddress, bid.BidAmount.String()))
|
||||||
|
|
||||||
|
secondHighestBid = bid
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Updated 2nd bid %s %s", secondHighestBid.BidderAddress, secondHighestBid.BidAmount.String()))
|
||||||
|
} else {
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Ignoring bid as it doesn't affect 1st/2nd price %s %s", bid.BidderAddress, bid.BidAmount.String()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Highest bid is the winner, but pays second highest bid price.
|
||||||
|
auction.Status = types.AuctionStatusCompleted
|
||||||
|
|
||||||
|
if highestBid != nil {
|
||||||
|
auction.WinnerAddress = highestBid.BidderAddress
|
||||||
|
auction.WinningBid = highestBid.BidAmount
|
||||||
|
|
||||||
|
// Winner pays 2nd price, if a 2nd price exists.
|
||||||
|
auction.WinningPrice = highestBid.BidAmount
|
||||||
|
if secondHighestBid != nil {
|
||||||
|
auction.WinningPrice = secondHighestBid.BidAmount
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Auction %s winner %s.", auction.Id, auction.WinnerAddress))
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Auction %s winner bid %s.", auction.Id, auction.WinningBid.String()))
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Auction %s winner price %s.", auction.Id, auction.WinningPrice.String()))
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Auction %s has no valid revealed bids (no winner).", auction.Id))
|
||||||
|
}
|
||||||
|
|
||||||
|
k.SaveAuction(ctx, auction)
|
||||||
|
|
||||||
|
for _, bid := range bids {
|
||||||
|
bidderAddress, err := sdk.AccAddressFromBech32(bid.BidderAddress)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Logger().Error(fmt.Sprintf("Invalid bidderAddress address. %v", err))
|
||||||
|
panic("Invalid bidder address.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if bid.Status == types.BidStatusRevealed {
|
||||||
|
// Send reveal fee back to bidders that've revealed the bid.
|
||||||
|
sdkErr := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, bidderAddress, sdk.NewCoins(bid.RevealFee))
|
||||||
|
if sdkErr != nil {
|
||||||
|
ctx.Logger().Error(fmt.Sprintf("Auction error returning reveal fee: %v", sdkErr))
|
||||||
|
panic(sdkErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send back locked bid amount to all bidders.
|
||||||
|
sdkErr := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, bidderAddress, sdk.NewCoins(bid.BidAmount))
|
||||||
|
if sdkErr != nil {
|
||||||
|
ctx.Logger().Error(fmt.Sprintf("Auction error returning bid amount: %v", sdkErr))
|
||||||
|
panic(sdkErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process winner account (if nobody bids, there won't be a winner).
|
||||||
|
if auction.WinnerAddress != "" {
|
||||||
|
winnerAddress, err := sdk.AccAddressFromBech32(auction.WinnerAddress)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Logger().Error(fmt.Sprintf("Invalid winner address. %v", err))
|
||||||
|
panic("Invalid winner address.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take 2nd price from winner.
|
||||||
|
sdkErr := k.bankKeeper.SendCoinsFromAccountToModule(ctx, winnerAddress, types.ModuleName, sdk.NewCoins(auction.WinningPrice))
|
||||||
|
if sdkErr != nil {
|
||||||
|
ctx.Logger().Error(fmt.Sprintf("Auction error taking funds from winner: %v", sdkErr))
|
||||||
|
panic(sdkErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Burn anything over the min. bid amount.
|
||||||
|
amountToBurn := auction.WinningPrice.Sub(auction.MinimumBid)
|
||||||
|
if amountToBurn.IsNegative() {
|
||||||
|
ctx.Logger().Error(fmt.Sprintf("Auction coins to burn cannot be negative."))
|
||||||
|
panic("Auction coins to burn cannot be negative.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use auction burn module account instead of actually burning coins to better keep track of supply.
|
||||||
|
sdkErr = k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, types.AuctionBurnModuleAccountName, sdk.NewCoins(amountToBurn))
|
||||||
|
if sdkErr != nil {
|
||||||
|
ctx.Logger().Error(fmt.Sprintf("Auction error burning coins: %v", sdkErr))
|
||||||
|
panic(sdkErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify other modules (hook).
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Auction %s notifying %d modules.", auction.Id, len(k.usageKeepers)))
|
||||||
|
for _, keeper := range k.usageKeepers {
|
||||||
|
ctx.Logger().Info(fmt.Sprintf("Auction %s notifying module %s.", auction.Id, keeper.ModuleName()))
|
||||||
|
keeper.OnAuctionWinnerSelected(ctx, auction.Id)
|
||||||
|
}
|
||||||
|
}
|
51
x/auction/keeper/keeper_test.go
Normal file
51
x/auction/keeper/keeper_test.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package keeper_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||||
|
"github.com/tharsis/ethermint/app"
|
||||||
|
auctionkeeper "github.com/tharsis/ethermint/x/auction/keeper"
|
||||||
|
"github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type KeeperTestSuite struct {
|
||||||
|
suite.Suite
|
||||||
|
app *app.EthermintApp
|
||||||
|
ctx sdk.Context
|
||||||
|
queryClient types.QueryClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) SetupTest() {
|
||||||
|
testApp := app.Setup(false)
|
||||||
|
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
|
||||||
|
|
||||||
|
querier := auctionkeeper.Querier{Keeper: testApp.AuctionKeeper}
|
||||||
|
|
||||||
|
queryHelper := baseapp.NewQueryServerTestHelper(ctx, testApp.InterfaceRegistry())
|
||||||
|
types.RegisterQueryServer(queryHelper, querier)
|
||||||
|
queryClient := types.NewQueryClient(queryHelper)
|
||||||
|
|
||||||
|
suite.app, suite.ctx, suite.queryClient = testApp, ctx, queryClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParams(t *testing.T) {
|
||||||
|
testApp := app.Setup(false)
|
||||||
|
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
|
||||||
|
|
||||||
|
expParams := types.DefaultParams()
|
||||||
|
params := testApp.AuctionKeeper.GetParams(ctx)
|
||||||
|
require.Equal(t, expParams.CommitsDuration, params.CommitsDuration)
|
||||||
|
require.Equal(t, expParams.RevealsDuration, params.RevealsDuration)
|
||||||
|
require.Equal(t, expParams.CommitFee, params.CommitFee)
|
||||||
|
require.Equal(t, expParams.RevealFee, params.RevealFee)
|
||||||
|
require.Equal(t, expParams.MinimumBid, params.MinimumBid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKeeperTestSuite(t *testing.T) {
|
||||||
|
suite.Run(t, new(KeeperTestSuite))
|
||||||
|
}
|
110
x/auction/keeper/msg_server.go
Normal file
110
x/auction/keeper/msg_server.go
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
package keeper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
|
||||||
|
"github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type msgServer struct {
|
||||||
|
Keeper
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMsgServer(keeper Keeper) types.MsgServer {
|
||||||
|
return &msgServer{Keeper: keeper}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ types.MsgServer = msgServer{}
|
||||||
|
|
||||||
|
func (s msgServer) CreateAuction(c context.Context, msg *types.MsgCreateAuction) (*types.MsgCreateAuctionResponse, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(c)
|
||||||
|
|
||||||
|
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := s.Keeper.CreateAuction(ctx, *msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.EventManager().EmitEvents(sdk.Events{
|
||||||
|
sdk.NewEvent(
|
||||||
|
types.EventTypeCreateAuction,
|
||||||
|
sdk.NewAttribute(types.AttributeKeyCommitsDuration, msg.CommitsDuration.String()),
|
||||||
|
sdk.NewAttribute(types.AttributeKeyCommitFee, msg.CommitFee.String()),
|
||||||
|
sdk.NewAttribute(types.AttributeKeyRevealFee, msg.RevealFee.String()),
|
||||||
|
sdk.NewAttribute(types.AttributeKeyMinimumBid, msg.MinimumBid.String()),
|
||||||
|
),
|
||||||
|
sdk.NewEvent(
|
||||||
|
sdk.EventTypeMessage,
|
||||||
|
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
|
||||||
|
sdk.NewAttribute(types.AttributeKeySigner, signerAddress.String()),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
|
||||||
|
return &types.MsgCreateAuctionResponse{Auction: resp}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitBid is the command for committing a bid
|
||||||
|
func (s msgServer) CommitBid(c context.Context, msg *types.MsgCommitBid) (*types.MsgCommitBidResponse, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(c)
|
||||||
|
|
||||||
|
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := s.Keeper.CommitBid(ctx, *msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.EventManager().EmitEvents(sdk.Events{
|
||||||
|
sdk.NewEvent(
|
||||||
|
types.EventTypeCommitBid,
|
||||||
|
sdk.NewAttribute(types.AttributeKeyAuctionID, msg.AuctionId),
|
||||||
|
sdk.NewAttribute(types.AttributeKeyCommitHash, msg.CommitHash),
|
||||||
|
),
|
||||||
|
sdk.NewEvent(
|
||||||
|
sdk.EventTypeMessage,
|
||||||
|
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
|
||||||
|
sdk.NewAttribute(types.AttributeKeySigner, signerAddress.String()),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
|
||||||
|
return &types.MsgCommitBidResponse{Bid: resp}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//RevealBid is the command for revealing a bid
|
||||||
|
func (s msgServer) RevealBid(c context.Context, msg *types.MsgRevealBid) (*types.MsgRevealBidResponse, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(c)
|
||||||
|
|
||||||
|
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := s.Keeper.RevealBid(ctx, *msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.EventManager().EmitEvents(sdk.Events{
|
||||||
|
sdk.NewEvent(
|
||||||
|
types.EventTypeRevealBid,
|
||||||
|
sdk.NewAttribute(types.AttributeKeyAuctionID, msg.AuctionId),
|
||||||
|
sdk.NewAttribute(types.AttributeKeyReveal, msg.Reveal),
|
||||||
|
),
|
||||||
|
sdk.NewEvent(
|
||||||
|
sdk.EventTypeMessage,
|
||||||
|
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
|
||||||
|
sdk.NewAttribute(types.AttributeKeySigner, signerAddress.String()),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
|
||||||
|
return &types.MsgRevealBidResponse{Auction: resp}, nil
|
||||||
|
}
|
18
x/auction/keeper/params.go
Normal file
18
x/auction/keeper/params.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package keeper
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
|
||||||
|
"github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetParams - Get all parameteras as types.Params.
|
||||||
|
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
|
||||||
|
k.paramSubspace.GetParamSet(ctx, ¶ms)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetParams - set the params.
|
||||||
|
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
|
||||||
|
k.paramSubspace.SetParamSet(ctx, ¶ms)
|
||||||
|
}
|
142
x/auction/module.go
Normal file
142
x/auction/module.go
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
package auction
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/module"
|
||||||
|
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
|
||||||
|
"github.com/tharsis/ethermint/x/auction/client/cli"
|
||||||
|
"github.com/tharsis/ethermint/x/auction/keeper"
|
||||||
|
"github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// type check to ensure the interface is properly implemented
|
||||||
|
var (
|
||||||
|
_ module.AppModule = AppModule{}
|
||||||
|
_ module.AppModuleBasic = AppModuleBasic{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// app module Basics object
|
||||||
|
type AppModuleBasic struct {
|
||||||
|
cdc codec.Codec
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b AppModuleBasic) Name() string {
|
||||||
|
return types.ModuleName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
|
||||||
|
types.RegisterLegacyAminoCodec(cdc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) {
|
||||||
|
types.RegisterInterfaces(registry)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b AppModuleBasic) DefaultGenesis(jsonCodec codec.JSONCodec) json.RawMessage {
|
||||||
|
return jsonCodec.MustMarshalJSON(types.DefaultGenesisState())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validation check of the Genesis
|
||||||
|
func (b AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error {
|
||||||
|
var data types.GenesisState
|
||||||
|
err := cdc.UnmarshalJSON(bz, &data)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)
|
||||||
|
}
|
||||||
|
// Once json successfully marshalled, passes along to genesis.go
|
||||||
|
return ValidateGenesis(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register rest routes
|
||||||
|
func (b AppModuleBasic) RegisterRESTRoutes(ctx client.Context, rtr *mux.Router) {
|
||||||
|
// No-op.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, serveMux *runtime.ServeMux) {
|
||||||
|
err := types.RegisterQueryHandlerClient(context.Background(), serveMux, types.NewQueryClient(clientCtx))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the root query command of this module
|
||||||
|
func (b AppModuleBasic) GetQueryCmd() *cobra.Command {
|
||||||
|
return cli.GetQueryCmd()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the root tx command of this module
|
||||||
|
func (b AppModuleBasic) GetTxCmd() *cobra.Command {
|
||||||
|
return cli.GetTxCmd()
|
||||||
|
}
|
||||||
|
|
||||||
|
type AppModule struct {
|
||||||
|
AppModuleBasic
|
||||||
|
keeper keeper.Keeper
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAppModule creates a new AppModule Object
|
||||||
|
func NewAppModule(cdc codec.Codec, k keeper.Keeper) AppModule {
|
||||||
|
return AppModule{
|
||||||
|
AppModuleBasic: AppModuleBasic{cdc: cdc},
|
||||||
|
keeper: k,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
|
||||||
|
keeper.RegisterInvariants(ir, am.keeper)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am AppModule) Route() sdk.Route {
|
||||||
|
return sdk.Route{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am AppModule) QuerierRoute() string {
|
||||||
|
return types.QuerierRoute
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am AppModule) LegacyQuerierHandler(cdc *codec.LegacyAmino) sdk.Querier {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am AppModule) RegisterServices(cfg module.Configurator) {
|
||||||
|
querier := keeper.Querier{Keeper: am.keeper}
|
||||||
|
types.RegisterQueryServer(cfg.QueryServer(), querier)
|
||||||
|
|
||||||
|
msgServer := keeper.NewMsgServer(am.keeper)
|
||||||
|
types.RegisterMsgServer(cfg.MsgServer(), msgServer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am AppModule) ConsensusVersion() uint64 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
|
||||||
|
|
||||||
|
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
|
||||||
|
return EndBlocker(ctx, am.keeper)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate {
|
||||||
|
var genesisState types.GenesisState
|
||||||
|
cdc.MustUnmarshalJSON(data, &genesisState)
|
||||||
|
InitGenesis(ctx, am.keeper, genesisState)
|
||||||
|
return []abci.ValidatorUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage {
|
||||||
|
gs := ExportGenesis(ctx, am.keeper)
|
||||||
|
return cdc.MustMarshalJSON(&gs)
|
||||||
|
}
|
24
x/auction/module_test.go
Normal file
24
x/auction/module_test.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package auction_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
abcitypes "github.com/tendermint/tendermint/abci/types"
|
||||||
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||||
|
app2 "github.com/tharsis/ethermint/app"
|
||||||
|
auctiontypes "github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestItCreatesModuleAccountOnInitBlock(t *testing.T) {
|
||||||
|
app := app2.Setup(false)
|
||||||
|
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||||
|
|
||||||
|
app.InitChain(abcitypes.RequestInitChain{
|
||||||
|
AppStateBytes: []byte("{}"),
|
||||||
|
ChainId: "test-chain-id",
|
||||||
|
})
|
||||||
|
|
||||||
|
acc := app.AccountKeeper.GetModuleAccount(ctx, auctiontypes.ModuleName)
|
||||||
|
require.NotNil(t, acc)
|
||||||
|
}
|
37
x/auction/types/codec.go
Normal file
37
x/auction/types/codec.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
|
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/msgservice"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RegisterLegacyAminoCodec registers the necessary x/auction interfaces and concrete types
|
||||||
|
// on the provided LegacyAmino codec. These types are used for Amino JSON serialization.
|
||||||
|
func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
|
||||||
|
cdc.RegisterConcrete(&MsgCreateAuction{}, "auction/MsgCreateAuction", nil)
|
||||||
|
cdc.RegisterConcrete(&MsgCommitBid{}, "auction/MsgCommitBid", nil)
|
||||||
|
cdc.RegisterConcrete(&MsgRevealBid{}, "auction/MsgRevealBid", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterInterfaces(registry types.InterfaceRegistry) {
|
||||||
|
registry.RegisterImplementations((*sdk.Msg)(nil),
|
||||||
|
&MsgCreateAuction{},
|
||||||
|
&MsgCommitBid{},
|
||||||
|
&MsgRevealBid{},
|
||||||
|
)
|
||||||
|
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
amino = codec.NewLegacyAmino()
|
||||||
|
ModuleCdc = codec.NewAminoCodec(amino)
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
RegisterLegacyAminoCodec(amino)
|
||||||
|
cryptocodec.RegisterCrypto(amino)
|
||||||
|
amino.Seal()
|
||||||
|
}
|
19
x/auction/types/events.go
Normal file
19
x/auction/types/events.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
const (
|
||||||
|
EventTypeCreateAuction = "create-auction"
|
||||||
|
EventTypeCommitBid = "commit-bid"
|
||||||
|
EventTypeRevealBid = "reveal-bid"
|
||||||
|
|
||||||
|
AttributeKeyCommitsDuration = "commits-duration"
|
||||||
|
AttributeKeyRevealsDuration = "reveals-duration"
|
||||||
|
AttributeKeyCommitFee = "commit-fee"
|
||||||
|
AttributeKeyRevealFee = "reveal-fee"
|
||||||
|
AttributeKeyMinimumBid = "minimum-bid"
|
||||||
|
AttributeKeySigner = "signer"
|
||||||
|
AttributeKeyAuctionID = "auction-id"
|
||||||
|
AttributeKeyCommitHash = "commit-hash"
|
||||||
|
AttributeKeyReveal = "reveal"
|
||||||
|
|
||||||
|
AttributeValueCategory = ModuleName
|
||||||
|
)
|
16
x/auction/types/expected_keepers.go
Normal file
16
x/auction/types/expected_keepers.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AuctionUsageKeeper keep track of auction usage in other modules.
|
||||||
|
// Used to, for example, prevent deletion of a auction that's in use.
|
||||||
|
type AuctionUsageKeeper interface {
|
||||||
|
ModuleName() string
|
||||||
|
UsesAuction(ctx sdk.Context, auctionID string) bool
|
||||||
|
|
||||||
|
OnAuction(ctx sdk.Context, auctionID string)
|
||||||
|
OnAuctionBid(ctx sdk.Context, auctionID string, bidderAddress string)
|
||||||
|
OnAuctionWinnerSelected(ctx sdk.Context, auctionID string)
|
||||||
|
}
|
9
x/auction/types/genesis.go
Normal file
9
x/auction/types/genesis.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
// DefaultGenesisState sets default evm genesis state with empty accounts and default params and
|
||||||
|
// chain config values.
|
||||||
|
func DefaultGenesisState() *GenesisState {
|
||||||
|
return &GenesisState{
|
||||||
|
Params: DefaultParams(),
|
||||||
|
}
|
||||||
|
}
|
389
x/auction/types/genesis.pb.go
Normal file
389
x/auction/types/genesis.pb.go
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||||
|
// source: vulcanize/auction/v1beta1/genesis.proto
|
||||||
|
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
fmt "fmt"
|
||||||
|
_ "github.com/gogo/protobuf/gogoproto"
|
||||||
|
proto "github.com/gogo/protobuf/proto"
|
||||||
|
io "io"
|
||||||
|
math "math"
|
||||||
|
math_bits "math/bits"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var _ = proto.Marshal
|
||||||
|
var _ = fmt.Errorf
|
||||||
|
var _ = math.Inf
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the proto package it is being compiled against.
|
||||||
|
// A compilation error at this line likely means your copy of the
|
||||||
|
// proto package needs to be updated.
|
||||||
|
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||||
|
|
||||||
|
// GenesisState defines the genesis state of the auction module
|
||||||
|
type GenesisState struct {
|
||||||
|
Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"`
|
||||||
|
Auctions []*Auction `protobuf:"bytes,2,rep,name=auctions,proto3" json:"auctions,omitempty" json:"bonds" yaml:"bonds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GenesisState) Reset() { *m = GenesisState{} }
|
||||||
|
func (m *GenesisState) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*GenesisState) ProtoMessage() {}
|
||||||
|
func (*GenesisState) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_23ebfbd3a1e67fe6, []int{0}
|
||||||
|
}
|
||||||
|
func (m *GenesisState) XXX_Unmarshal(b []byte) error {
|
||||||
|
return m.Unmarshal(b)
|
||||||
|
}
|
||||||
|
func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
if deterministic {
|
||||||
|
return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic)
|
||||||
|
} else {
|
||||||
|
b = b[:cap(b)]
|
||||||
|
n, err := m.MarshalToSizedBuffer(b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return b[:n], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (m *GenesisState) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_GenesisState.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *GenesisState) XXX_Size() int {
|
||||||
|
return m.Size()
|
||||||
|
}
|
||||||
|
func (m *GenesisState) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_GenesisState.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_GenesisState proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *GenesisState) GetParams() Params {
|
||||||
|
if m != nil {
|
||||||
|
return m.Params
|
||||||
|
}
|
||||||
|
return Params{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GenesisState) GetAuctions() []*Auction {
|
||||||
|
if m != nil {
|
||||||
|
return m.Auctions
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
proto.RegisterType((*GenesisState)(nil), "vulcanize.auction.v1beta1.GenesisState")
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
proto.RegisterFile("vulcanize/auction/v1beta1/genesis.proto", fileDescriptor_23ebfbd3a1e67fe6)
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileDescriptor_23ebfbd3a1e67fe6 = []byte{
|
||||||
|
// 264 bytes of a gzipped FileDescriptorProto
|
||||||
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2f, 0x2b, 0xcd, 0x49,
|
||||||
|
0x4e, 0xcc, 0xcb, 0xac, 0x4a, 0xd5, 0x4f, 0x2c, 0x4d, 0x2e, 0xc9, 0xcc, 0xcf, 0xd3, 0x2f, 0x33,
|
||||||
|
0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28,
|
||||||
|
0xca, 0x2f, 0xc9, 0x17, 0x92, 0x84, 0x2b, 0xd4, 0x83, 0x2a, 0xd4, 0x83, 0x2a, 0x94, 0x12, 0x49,
|
||||||
|
0xcf, 0x4f, 0xcf, 0x07, 0xab, 0xd2, 0x07, 0xb1, 0x20, 0x1a, 0xa4, 0x54, 0x71, 0x9b, 0x5c, 0x52,
|
||||||
|
0x59, 0x90, 0x0a, 0x35, 0x57, 0x69, 0x1d, 0x23, 0x17, 0x8f, 0x3b, 0xc4, 0xa6, 0xe0, 0x92, 0xc4,
|
||||||
|
0x92, 0x54, 0x21, 0x7b, 0x2e, 0xb6, 0x82, 0xc4, 0xa2, 0xc4, 0xdc, 0x62, 0x09, 0x46, 0x05, 0x46,
|
||||||
|
0x0d, 0x6e, 0x23, 0x45, 0x3d, 0x9c, 0x36, 0xeb, 0x05, 0x80, 0x15, 0x3a, 0xb1, 0x9c, 0xb8, 0x27,
|
||||||
|
0xcf, 0x10, 0x04, 0xd5, 0x26, 0x14, 0xcb, 0xc5, 0x01, 0x55, 0x57, 0x2c, 0xc1, 0xa4, 0xc0, 0xac,
|
||||||
|
0xc1, 0x6d, 0xa4, 0x84, 0xc7, 0x08, 0x47, 0x08, 0xdf, 0x49, 0xf6, 0xd3, 0x3d, 0x79, 0xc9, 0xac,
|
||||||
|
0xe2, 0xfc, 0x3c, 0x2b, 0xa5, 0xa4, 0xfc, 0xbc, 0x94, 0x62, 0x25, 0x85, 0xca, 0xc4, 0xdc, 0x1c,
|
||||||
|
0x18, 0x27, 0x08, 0x6e, 0xa4, 0x93, 0xdb, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e,
|
||||||
|
0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31,
|
||||||
|
0x44, 0xe9, 0xa4, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x97, 0x64, 0x24,
|
||||||
|
0x16, 0x15, 0x67, 0x16, 0xeb, 0xa7, 0x96, 0x64, 0xa4, 0x16, 0xe5, 0x66, 0xe6, 0x95, 0xe8, 0x57,
|
||||||
|
0xc0, 0x83, 0x01, 0xec, 0xfd, 0x24, 0x36, 0xb0, 0xff, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff,
|
||||||
|
0x40, 0x0a, 0x31, 0x1a, 0x82, 0x01, 0x00, 0x00,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GenesisState) Marshal() (dAtA []byte, err error) {
|
||||||
|
size := m.Size()
|
||||||
|
dAtA = make([]byte, size)
|
||||||
|
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dAtA[:n], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) {
|
||||||
|
size := m.Size()
|
||||||
|
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
|
i := len(dAtA)
|
||||||
|
_ = i
|
||||||
|
var l int
|
||||||
|
_ = l
|
||||||
|
if len(m.Auctions) > 0 {
|
||||||
|
for iNdEx := len(m.Auctions) - 1; iNdEx >= 0; iNdEx-- {
|
||||||
|
{
|
||||||
|
size, err := m.Auctions[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
i -= size
|
||||||
|
i = encodeVarintGenesis(dAtA, i, uint64(size))
|
||||||
|
}
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0x12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
size, err := m.Params.MarshalToSizedBuffer(dAtA[:i])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
i -= size
|
||||||
|
i = encodeVarintGenesis(dAtA, i, uint64(size))
|
||||||
|
}
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0xa
|
||||||
|
return len(dAtA) - i, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int {
|
||||||
|
offset -= sovGenesis(v)
|
||||||
|
base := offset
|
||||||
|
for v >= 1<<7 {
|
||||||
|
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||||
|
v >>= 7
|
||||||
|
offset++
|
||||||
|
}
|
||||||
|
dAtA[offset] = uint8(v)
|
||||||
|
return base
|
||||||
|
}
|
||||||
|
func (m *GenesisState) Size() (n int) {
|
||||||
|
if m == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
var l int
|
||||||
|
_ = l
|
||||||
|
l = m.Params.Size()
|
||||||
|
n += 1 + l + sovGenesis(uint64(l))
|
||||||
|
if len(m.Auctions) > 0 {
|
||||||
|
for _, e := range m.Auctions {
|
||||||
|
l = e.Size()
|
||||||
|
n += 1 + l + sovGenesis(uint64(l))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func sovGenesis(x uint64) (n int) {
|
||||||
|
return (math_bits.Len64(x|1) + 6) / 7
|
||||||
|
}
|
||||||
|
func sozGenesis(x uint64) (n int) {
|
||||||
|
return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||||
|
}
|
||||||
|
func (m *GenesisState) Unmarshal(dAtA []byte) error {
|
||||||
|
l := len(dAtA)
|
||||||
|
iNdEx := 0
|
||||||
|
for iNdEx < l {
|
||||||
|
preIndex := iNdEx
|
||||||
|
var wire uint64
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowGenesis
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
wire |= uint64(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fieldNum := int32(wire >> 3)
|
||||||
|
wireType := int(wire & 0x7)
|
||||||
|
if wireType == 4 {
|
||||||
|
return fmt.Errorf("proto: GenesisState: wiretype end group for non-group")
|
||||||
|
}
|
||||||
|
if fieldNum <= 0 {
|
||||||
|
return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||||
|
}
|
||||||
|
switch fieldNum {
|
||||||
|
case 1:
|
||||||
|
if wireType != 2 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
|
||||||
|
}
|
||||||
|
var msglen int
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowGenesis
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
msglen |= int(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if msglen < 0 {
|
||||||
|
return ErrInvalidLengthGenesis
|
||||||
|
}
|
||||||
|
postIndex := iNdEx + msglen
|
||||||
|
if postIndex < 0 {
|
||||||
|
return ErrInvalidLengthGenesis
|
||||||
|
}
|
||||||
|
if postIndex > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
iNdEx = postIndex
|
||||||
|
case 2:
|
||||||
|
if wireType != 2 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field Auctions", wireType)
|
||||||
|
}
|
||||||
|
var msglen int
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowGenesis
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
msglen |= int(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if msglen < 0 {
|
||||||
|
return ErrInvalidLengthGenesis
|
||||||
|
}
|
||||||
|
postIndex := iNdEx + msglen
|
||||||
|
if postIndex < 0 {
|
||||||
|
return ErrInvalidLengthGenesis
|
||||||
|
}
|
||||||
|
if postIndex > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
m.Auctions = append(m.Auctions, &Auction{})
|
||||||
|
if err := m.Auctions[len(m.Auctions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
iNdEx = postIndex
|
||||||
|
default:
|
||||||
|
iNdEx = preIndex
|
||||||
|
skippy, err := skipGenesis(dAtA[iNdEx:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||||
|
return ErrInvalidLengthGenesis
|
||||||
|
}
|
||||||
|
if (iNdEx + skippy) > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
iNdEx += skippy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if iNdEx > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func skipGenesis(dAtA []byte) (n int, err error) {
|
||||||
|
l := len(dAtA)
|
||||||
|
iNdEx := 0
|
||||||
|
depth := 0
|
||||||
|
for iNdEx < l {
|
||||||
|
var wire uint64
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return 0, ErrIntOverflowGenesis
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return 0, io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
wire |= (uint64(b) & 0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wireType := int(wire & 0x7)
|
||||||
|
switch wireType {
|
||||||
|
case 0:
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return 0, ErrIntOverflowGenesis
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return 0, io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
iNdEx++
|
||||||
|
if dAtA[iNdEx-1] < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
iNdEx += 8
|
||||||
|
case 2:
|
||||||
|
var length int
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return 0, ErrIntOverflowGenesis
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return 0, io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
length |= (int(b) & 0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if length < 0 {
|
||||||
|
return 0, ErrInvalidLengthGenesis
|
||||||
|
}
|
||||||
|
iNdEx += length
|
||||||
|
case 3:
|
||||||
|
depth++
|
||||||
|
case 4:
|
||||||
|
if depth == 0 {
|
||||||
|
return 0, ErrUnexpectedEndOfGroupGenesis
|
||||||
|
}
|
||||||
|
depth--
|
||||||
|
case 5:
|
||||||
|
iNdEx += 4
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||||
|
}
|
||||||
|
if iNdEx < 0 {
|
||||||
|
return 0, ErrInvalidLengthGenesis
|
||||||
|
}
|
||||||
|
if depth == 0 {
|
||||||
|
return iNdEx, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||||
|
ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow")
|
||||||
|
ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group")
|
||||||
|
)
|
18
x/auction/types/key.go
Normal file
18
x/auction/types/key.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ModuleName is the name of the module
|
||||||
|
ModuleName = "auction"
|
||||||
|
|
||||||
|
// AuctionBurnModuleAccountName is the name of the auction burn module account.
|
||||||
|
AuctionBurnModuleAccountName = "auction_burn"
|
||||||
|
|
||||||
|
// StoreKey to be used when creating the KVStore
|
||||||
|
StoreKey = ModuleName
|
||||||
|
|
||||||
|
// QuerierRoute is the querier route for the staking module
|
||||||
|
QuerierRoute = ModuleName
|
||||||
|
|
||||||
|
// RouterKey is the msg router key for the staking module
|
||||||
|
RouterKey = ModuleName
|
||||||
|
)
|
150
x/auction/types/msgs.go
Normal file
150
x/auction/types/msgs.go
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ sdk.Msg = &MsgCreateAuction{}
|
||||||
|
_ sdk.Msg = &MsgCommitBid{}
|
||||||
|
_ sdk.Msg = &MsgRevealBid{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewMsgCreateAuction is the constructor function for MsgCreateAuction.
|
||||||
|
func NewMsgCreateAuction(params Params, signer sdk.AccAddress) MsgCreateAuction {
|
||||||
|
return MsgCreateAuction{
|
||||||
|
CommitsDuration: params.CommitsDuration,
|
||||||
|
RevealsDuration: params.RevealsDuration,
|
||||||
|
CommitFee: params.CommitFee,
|
||||||
|
RevealFee: params.RevealFee,
|
||||||
|
MinimumBid: params.MinimumBid,
|
||||||
|
Signer: signer.String(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Route Implements Msg.
|
||||||
|
func (msg MsgCreateAuction) Route() string { return RouterKey }
|
||||||
|
|
||||||
|
// Type Implements Msg.
|
||||||
|
func (msg MsgCreateAuction) Type() string { return "create" }
|
||||||
|
|
||||||
|
// ValidateBasic Implements Msg.
|
||||||
|
func (msg MsgCreateAuction) ValidateBasic() error {
|
||||||
|
if msg.Signer == "" {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Signer)
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg.CommitsDuration <= 0 {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "commit phase duration invalid.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg.RevealsDuration <= 0 {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "reveal phase duration invalid.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !msg.MinimumBid.IsPositive() {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "minimum bid should be greater than zero.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSignBytes Implements Msg.
|
||||||
|
func (msg MsgCreateAuction) GetSignBytes() []byte {
|
||||||
|
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSigners Implements Msg.
|
||||||
|
func (msg MsgCreateAuction) GetSigners() []sdk.AccAddress {
|
||||||
|
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
|
||||||
|
return []sdk.AccAddress{accAddr}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgCommitBid is the constructor function for MsgCommitBid.
|
||||||
|
func NewMsgCommitBid(auctionID string, commitHash string, signer sdk.AccAddress) MsgCommitBid {
|
||||||
|
|
||||||
|
return MsgCommitBid{
|
||||||
|
AuctionId: auctionID,
|
||||||
|
CommitHash: commitHash,
|
||||||
|
Signer: signer.String(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Route Implements Msg.
|
||||||
|
func (msg MsgCommitBid) Route() string { return RouterKey }
|
||||||
|
|
||||||
|
// Type Implements Msg.
|
||||||
|
func (msg MsgCommitBid) Type() string { return "commit" }
|
||||||
|
|
||||||
|
// ValidateBasic Implements Msg.
|
||||||
|
func (msg MsgCommitBid) ValidateBasic() error {
|
||||||
|
if msg.Signer == "" {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer address.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg.AuctionId == "" {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid auction ID.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg.CommitHash == "" {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid commit hash.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSignBytes Implements Msg.
|
||||||
|
func (msg MsgCommitBid) GetSignBytes() []byte {
|
||||||
|
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSigners Implements Msg.
|
||||||
|
func (msg MsgCommitBid) GetSigners() []sdk.AccAddress {
|
||||||
|
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
|
||||||
|
return []sdk.AccAddress{accAddr}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgRevealBid is the constructor function for MsgRevealBid.
|
||||||
|
func NewMsgRevealBid(auctionID string, reveal string, signer sdk.AccAddress) MsgRevealBid {
|
||||||
|
|
||||||
|
return MsgRevealBid{
|
||||||
|
AuctionId: auctionID,
|
||||||
|
Reveal: reveal,
|
||||||
|
Signer: signer.String(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Route Implements Msg.
|
||||||
|
func (msg MsgRevealBid) Route() string { return RouterKey }
|
||||||
|
|
||||||
|
// Type Implements Msg.
|
||||||
|
func (msg MsgRevealBid) Type() string { return "reveal" }
|
||||||
|
|
||||||
|
// ValidateBasic Implements Msg.
|
||||||
|
func (msg MsgRevealBid) ValidateBasic() error {
|
||||||
|
if msg.Signer == "" {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer address.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg.AuctionId == "" {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid auction ID.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg.Reveal == "" {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid reveal data.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSignBytes Implements Msg.
|
||||||
|
func (msg MsgRevealBid) GetSignBytes() []byte {
|
||||||
|
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSigners Implements Msg.
|
||||||
|
func (msg MsgRevealBid) GetSigners() []sdk.AccAddress {
|
||||||
|
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
|
||||||
|
return []sdk.AccAddress{accAddr}
|
||||||
|
}
|
173
x/auction/types/params.go
Normal file
173
x/auction/types/params.go
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/params/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Default parameter namespace.
|
||||||
|
const (
|
||||||
|
DefaultParamspace = ModuleName
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
DefaultCommitsDuration = 5 * time.Minute
|
||||||
|
DefaultRevealsDuration = 5 * time.Minute
|
||||||
|
DefaultCommitFee = sdk.Coin{Amount: sdk.NewInt(10), Denom: sdk.DefaultBondDenom}
|
||||||
|
DefaultRevealFee = sdk.Coin{Amount: sdk.NewInt(10), Denom: sdk.DefaultBondDenom}
|
||||||
|
DefaultMinimumBid = sdk.Coin{Amount: sdk.NewInt(1000), Denom: sdk.DefaultBondDenom}
|
||||||
|
|
||||||
|
ParamStoreKeyCommitsDuration = []byte("CommitsDuration")
|
||||||
|
ParamStoreKeyRevealsDuration = []byte("RevealsDuration")
|
||||||
|
ParamStoreKeyCommitFee = []byte("CommitFee")
|
||||||
|
ParamStoreKeyRevealFee = []byte("RevealFee")
|
||||||
|
ParamStoreKeyMinimumBid = []byte("MinimumBid")
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ types.ParamSet = &Params{}
|
||||||
|
|
||||||
|
func NewParams() Params {
|
||||||
|
return DefaultParams()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParamKeyTable - ParamTable for bond module.
|
||||||
|
func ParamKeyTable() types.KeyTable {
|
||||||
|
return types.NewKeyTable().RegisterParamSet(&Params{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParamSetPairs - implements params.ParamSet
|
||||||
|
func (p *Params) ParamSetPairs() types.ParamSetPairs {
|
||||||
|
return types.ParamSetPairs{
|
||||||
|
types.NewParamSetPair(ParamStoreKeyCommitsDuration, &p.CommitsDuration, validateCommitsDuration),
|
||||||
|
types.NewParamSetPair(ParamStoreKeyRevealsDuration, &p.RevealsDuration, validateRevealsDuration),
|
||||||
|
types.NewParamSetPair(ParamStoreKeyCommitFee, &p.CommitFee, validateCommitFee),
|
||||||
|
types.NewParamSetPair(ParamStoreKeyRevealFee, &p.RevealFee, validateRevealFee),
|
||||||
|
types.NewParamSetPair(ParamStoreKeyMinimumBid, &p.MinimumBid, validateMinimumBid),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal returns a boolean determining if two Params types are identical.
|
||||||
|
func (p Params) Equal(p2 Params) bool {
|
||||||
|
bz1 := ModuleCdc.MustMarshalLengthPrefixed(&p)
|
||||||
|
bz2 := ModuleCdc.MustMarshalLengthPrefixed(&p2)
|
||||||
|
return bytes.Equal(bz1, bz2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultParams returns a default set of parameters.
|
||||||
|
func DefaultParams() Params {
|
||||||
|
return Params{
|
||||||
|
CommitsDuration: DefaultCommitsDuration,
|
||||||
|
RevealsDuration: DefaultRevealsDuration,
|
||||||
|
CommitFee: DefaultCommitFee,
|
||||||
|
RevealFee: DefaultRevealFee,
|
||||||
|
MinimumBid: DefaultMinimumBid,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a human readable string representation of the parameters.
|
||||||
|
func (p Params) String() string {
|
||||||
|
var sb strings.Builder
|
||||||
|
sb.WriteString("Params: \n")
|
||||||
|
sb.WriteString(fmt.Sprintf("CommitsDuration: %s\n", p.CommitsDuration.String()))
|
||||||
|
sb.WriteString(fmt.Sprintf("RevealsDuration: %s\n", p.RevealsDuration.String()))
|
||||||
|
sb.WriteString(fmt.Sprintf("CommitFee: %s\n", p.CommitFee.String()))
|
||||||
|
sb.WriteString(fmt.Sprintf("RevealFee: %s\n", p.RevealFee.String()))
|
||||||
|
sb.WriteString(fmt.Sprintf("MinimumBid: %s\n", p.MinimumBid.String()))
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateCommitsDuration(i interface{}) error {
|
||||||
|
v, ok := i.(time.Duration)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("invalid parameter type: %T", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v < 0 {
|
||||||
|
return errors.New("commits duration cannot be negative")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateRevealsDuration(i interface{}) error {
|
||||||
|
v, ok := i.(time.Duration)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("invalid parameter type: %T", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v < 0 {
|
||||||
|
return errors.New("commits duration cannot be negative")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateCommitFee(i interface{}) error {
|
||||||
|
v, ok := i.(sdk.Coin)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("invalid parameter type: %T", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Amount.IsNegative() {
|
||||||
|
return errors.New("commit fee must be positive")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateRevealFee(i interface{}) error {
|
||||||
|
v, ok := i.(sdk.Coin)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("invalid parameter type: %T", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Amount.IsNegative() {
|
||||||
|
return errors.New("reveal fee must be positive")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateMinimumBid(i interface{}) error {
|
||||||
|
v, ok := i.(sdk.Coin)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("invalid parameter type: %T", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Amount.IsNegative() {
|
||||||
|
return errors.New("minimum bid must be positive")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate a set of params.
|
||||||
|
func (p Params) Validate() error {
|
||||||
|
if err := validateCommitsDuration(p.CommitsDuration); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validateRevealsDuration(p.RevealsDuration); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validateCommitFee(p.CommitFee); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validateRevealFee(p.RevealFee); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validateMinimumBid(p.MinimumBid); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
3390
x/auction/types/query.pb.go
Normal file
3390
x/auction/types/query.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
802
x/auction/types/query.pb.gw.go
Normal file
802
x/auction/types/query.pb.gw.go
Normal file
@ -0,0 +1,802 @@
|
|||||||
|
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
|
||||||
|
// source: vulcanize/auction/v1beta1/query.proto
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package types is a reverse proxy.
|
||||||
|
|
||||||
|
It translates gRPC into RESTful JSON APIs.
|
||||||
|
*/
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/descriptor"
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||||
|
"github.com/grpc-ecosystem/grpc-gateway/utilities"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/grpclog"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Suppress "imported and not used" errors
|
||||||
|
var _ codes.Code
|
||||||
|
var _ io.Reader
|
||||||
|
var _ status.Status
|
||||||
|
var _ = runtime.String
|
||||||
|
var _ = utilities.NewDoubleArray
|
||||||
|
var _ = descriptor.ForMessage
|
||||||
|
|
||||||
|
var (
|
||||||
|
filter_Query_Auctions_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||||
|
)
|
||||||
|
|
||||||
|
func request_Query_Auctions_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq AuctionsRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
if err := req.ParseForm(); err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Auctions_0); err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := client.Auctions(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func local_request_Query_Auctions_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq AuctionsRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
if err := req.ParseForm(); err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Auctions_0); err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := server.Auctions(ctx, &protoReq)
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func request_Query_GetAuction_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq AuctionRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
var (
|
||||||
|
val string
|
||||||
|
ok bool
|
||||||
|
err error
|
||||||
|
_ = err
|
||||||
|
)
|
||||||
|
|
||||||
|
val, ok = pathParams["id"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||||
|
}
|
||||||
|
|
||||||
|
protoReq.Id, err = runtime.String(val)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := client.GetAuction(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func local_request_Query_GetAuction_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq AuctionRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
var (
|
||||||
|
val string
|
||||||
|
ok bool
|
||||||
|
err error
|
||||||
|
_ = err
|
||||||
|
)
|
||||||
|
|
||||||
|
val, ok = pathParams["id"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||||
|
}
|
||||||
|
|
||||||
|
protoReq.Id, err = runtime.String(val)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := server.GetAuction(ctx, &protoReq)
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func request_Query_GetBid_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq BidRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
var (
|
||||||
|
val string
|
||||||
|
ok bool
|
||||||
|
err error
|
||||||
|
_ = err
|
||||||
|
)
|
||||||
|
|
||||||
|
val, ok = pathParams["auction_id"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auction_id")
|
||||||
|
}
|
||||||
|
|
||||||
|
protoReq.AuctionId, err = runtime.String(val)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auction_id", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
val, ok = pathParams["bidder"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "bidder")
|
||||||
|
}
|
||||||
|
|
||||||
|
protoReq.Bidder, err = runtime.String(val)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "bidder", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := client.GetBid(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func local_request_Query_GetBid_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq BidRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
var (
|
||||||
|
val string
|
||||||
|
ok bool
|
||||||
|
err error
|
||||||
|
_ = err
|
||||||
|
)
|
||||||
|
|
||||||
|
val, ok = pathParams["auction_id"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auction_id")
|
||||||
|
}
|
||||||
|
|
||||||
|
protoReq.AuctionId, err = runtime.String(val)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auction_id", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
val, ok = pathParams["bidder"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "bidder")
|
||||||
|
}
|
||||||
|
|
||||||
|
protoReq.Bidder, err = runtime.String(val)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "bidder", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := server.GetBid(ctx, &protoReq)
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func request_Query_GetBids_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq BidsRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
var (
|
||||||
|
val string
|
||||||
|
ok bool
|
||||||
|
err error
|
||||||
|
_ = err
|
||||||
|
)
|
||||||
|
|
||||||
|
val, ok = pathParams["auction_id"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auction_id")
|
||||||
|
}
|
||||||
|
|
||||||
|
protoReq.AuctionId, err = runtime.String(val)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auction_id", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := client.GetBids(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func local_request_Query_GetBids_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq BidsRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
var (
|
||||||
|
val string
|
||||||
|
ok bool
|
||||||
|
err error
|
||||||
|
_ = err
|
||||||
|
)
|
||||||
|
|
||||||
|
val, ok = pathParams["auction_id"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auction_id")
|
||||||
|
}
|
||||||
|
|
||||||
|
protoReq.AuctionId, err = runtime.String(val)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auction_id", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := server.GetBids(ctx, &protoReq)
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func request_Query_AuctionsByBidder_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq AuctionsByBidderRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
var (
|
||||||
|
val string
|
||||||
|
ok bool
|
||||||
|
err error
|
||||||
|
_ = err
|
||||||
|
)
|
||||||
|
|
||||||
|
val, ok = pathParams["bidder_address"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "bidder_address")
|
||||||
|
}
|
||||||
|
|
||||||
|
protoReq.BidderAddress, err = runtime.String(val)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "bidder_address", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := client.AuctionsByBidder(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func local_request_Query_AuctionsByBidder_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq AuctionsByBidderRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
var (
|
||||||
|
val string
|
||||||
|
ok bool
|
||||||
|
err error
|
||||||
|
_ = err
|
||||||
|
)
|
||||||
|
|
||||||
|
val, ok = pathParams["bidder_address"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "bidder_address")
|
||||||
|
}
|
||||||
|
|
||||||
|
protoReq.BidderAddress, err = runtime.String(val)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "bidder_address", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := server.AuctionsByBidder(ctx, &protoReq)
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func request_Query_AuctionsByOwner_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq AuctionsByOwnerRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
var (
|
||||||
|
val string
|
||||||
|
ok bool
|
||||||
|
err error
|
||||||
|
_ = err
|
||||||
|
)
|
||||||
|
|
||||||
|
val, ok = pathParams["owner_address"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "owner_address")
|
||||||
|
}
|
||||||
|
|
||||||
|
protoReq.OwnerAddress, err = runtime.String(val)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "owner_address", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := client.AuctionsByOwner(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func local_request_Query_AuctionsByOwner_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq AuctionsByOwnerRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
var (
|
||||||
|
val string
|
||||||
|
ok bool
|
||||||
|
err error
|
||||||
|
_ = err
|
||||||
|
)
|
||||||
|
|
||||||
|
val, ok = pathParams["owner_address"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "owner_address")
|
||||||
|
}
|
||||||
|
|
||||||
|
protoReq.OwnerAddress, err = runtime.String(val)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "owner_address", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := server.AuctionsByOwner(ctx, &protoReq)
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func request_Query_QueryParams_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq QueryParamsRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
msg, err := client.QueryParams(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func local_request_Query_QueryParams_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq QueryParamsRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
msg, err := server.QueryParams(ctx, &protoReq)
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func request_Query_Balance_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq BalanceRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
msg, err := client.Balance(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func local_request_Query_Balance_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq BalanceRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
msg, err := server.Balance(ctx, &protoReq)
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
|
||||||
|
// UnaryRPC :call QueryServer directly.
|
||||||
|
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||||
|
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
|
||||||
|
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_Auctions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_Query_Auctions_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_Auctions_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_GetAuction_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_Query_GetAuction_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_GetAuction_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_GetBid_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_Query_GetBid_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_GetBid_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_GetBids_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_Query_GetBids_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_GetBids_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_AuctionsByBidder_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_Query_AuctionsByBidder_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_AuctionsByBidder_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_AuctionsByOwner_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_Query_AuctionsByOwner_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_AuctionsByOwner_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_QueryParams_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_Query_QueryParams_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_QueryParams_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_Balance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_Query_Balance_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_Balance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but
|
||||||
|
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||||
|
func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||||
|
conn, err := grpc.Dial(endpoint, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
if cerr := conn.Close(); cerr != nil {
|
||||||
|
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
<-ctx.Done()
|
||||||
|
if cerr := conn.Close(); cerr != nil {
|
||||||
|
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return RegisterQueryHandler(ctx, mux, conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterQueryHandler registers the http handlers for service Query to "mux".
|
||||||
|
// The handlers forward requests to the grpc endpoint over "conn".
|
||||||
|
func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
|
||||||
|
return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterQueryHandlerClient registers the http handlers for service Query
|
||||||
|
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient".
|
||||||
|
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient"
|
||||||
|
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
|
||||||
|
// "QueryClient" to call the correct interceptors.
|
||||||
|
func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error {
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_Auctions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_Query_Auctions_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_Auctions_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_GetAuction_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_Query_GetAuction_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_GetAuction_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_GetBid_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_Query_GetBid_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_GetBid_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_GetBids_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_Query_GetBids_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_GetBids_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_AuctionsByBidder_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_Query_AuctionsByBidder_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_AuctionsByBidder_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_AuctionsByOwner_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_Query_AuctionsByOwner_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_AuctionsByOwner_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_QueryParams_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_Query_QueryParams_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_QueryParams_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_Query_Balance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_Query_Balance_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||||
|
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_Query_Balance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
pattern_Query_Auctions_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"vulcanize", "auction", "v1beta1", "auctions"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||||
|
|
||||||
|
pattern_Query_GetAuction_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"vulcanize", "auction", "v1beta1", "auctions", "id"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||||
|
|
||||||
|
pattern_Query_GetBid_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"vulcanize", "auction", "v1beta1", "bids", "auction_id", "bidder"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||||
|
|
||||||
|
pattern_Query_GetBids_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"vulcanize", "auction", "v1beta1", "bids", "auction_id"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||||
|
|
||||||
|
pattern_Query_AuctionsByBidder_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"vulcanize", "auction", "v1beta1", "by-bidder", "bidder_address"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||||
|
|
||||||
|
pattern_Query_AuctionsByOwner_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"vulcanize", "auction", "v1beta1", "by-owner", "owner_address"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||||
|
|
||||||
|
pattern_Query_QueryParams_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"vulcanize", "auction", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||||
|
|
||||||
|
pattern_Query_Balance_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"vulcanize", "auction", "v1beta1", "balance"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
forward_Query_Auctions_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
|
forward_Query_GetAuction_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
|
forward_Query_GetBid_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
|
forward_Query_GetBids_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
|
forward_Query_AuctionsByBidder_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
|
forward_Query_AuctionsByOwner_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
|
forward_Query_QueryParams_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
|
forward_Query_Balance_0 = runtime.ForwardResponseMessage
|
||||||
|
)
|
1777
x/auction/types/tx.pb.go
Normal file
1777
x/auction/types/tx.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
65
x/auction/types/types.go
Normal file
65
x/auction/types/types.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Auction status values.
|
||||||
|
const (
|
||||||
|
// Auction is in commit phase.
|
||||||
|
AuctionStatusCommitPhase = "commit"
|
||||||
|
|
||||||
|
// Auction is in reveal phase.
|
||||||
|
AuctionStatusRevealPhase = "reveal"
|
||||||
|
|
||||||
|
// Auction has ended (no reveals allowed).
|
||||||
|
AuctionStatusExpired = "expired"
|
||||||
|
|
||||||
|
// Auction has completed (winner selected).
|
||||||
|
AuctionStatusCompleted = "completed"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Bid status values.
|
||||||
|
const (
|
||||||
|
BidStatusCommitted = "commit"
|
||||||
|
BidStatusRevealed = "reveal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AuctionID simplifies generation of auction IDs.
|
||||||
|
type AuctionID struct {
|
||||||
|
Address sdk.Address
|
||||||
|
AccNum uint64
|
||||||
|
Sequence uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate creates the auction ID.
|
||||||
|
func (auctionID AuctionID) Generate() string {
|
||||||
|
hasher := sha256.New()
|
||||||
|
str := fmt.Sprintf("%s:%d:%d", auctionID.Address.String(), auctionID.AccNum, auctionID.Sequence)
|
||||||
|
hasher.Write([]byte(str))
|
||||||
|
return hex.EncodeToString(hasher.Sum(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (auction Auction) GetCreateTime() string {
|
||||||
|
return string(sdk.FormatTimeBytes(auction.CreateTime))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (auction Auction) GetCommitsEndTime() string {
|
||||||
|
return string(sdk.FormatTimeBytes(auction.CommitsEndTime))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (auction Auction) GetRevealsEndTime() string {
|
||||||
|
return string(sdk.FormatTimeBytes(auction.RevealsEndTime))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bid Bid) GetCommitTime() string {
|
||||||
|
return string(sdk.FormatTimeBytes(bid.CommitTime))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bid Bid) GetRevealTime() string {
|
||||||
|
return string(sdk.FormatTimeBytes(bid.RevealTime))
|
||||||
|
}
|
1943
x/auction/types/types.pb.go
Normal file
1943
x/auction/types/types.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
58
x/auth/ante/ante.go
Normal file
58
x/auth/ante/ante.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package ante
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
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/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandlerOptions are the options required for constructing a default SDK AnteHandler.
|
||||||
|
type HandlerOptions struct {
|
||||||
|
AccountKeeper AccountKeeper
|
||||||
|
BankKeeper types.BankKeeper
|
||||||
|
FeegrantKeeper FeegrantKeeper
|
||||||
|
SignModeHandler authsigning.SignModeHandler
|
||||||
|
SigGasConsumer func(meter sdk.GasMeter, sig signing.SignatureV2, params types.Params) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAnteHandler returns an AnteHandler that checks and increments sequence
|
||||||
|
// numbers, checks signatures & account numbers, and deducts fees from the first
|
||||||
|
// signer.
|
||||||
|
func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
||||||
|
if options.AccountKeeper == nil {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for ante builder")
|
||||||
|
}
|
||||||
|
|
||||||
|
if options.BankKeeper == nil {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for ante builder")
|
||||||
|
}
|
||||||
|
|
||||||
|
if options.SignModeHandler == nil {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder")
|
||||||
|
}
|
||||||
|
|
||||||
|
var sigGasConsumer = options.SigGasConsumer
|
||||||
|
if sigGasConsumer == nil {
|
||||||
|
sigGasConsumer = DefaultSigVerificationGasConsumer
|
||||||
|
}
|
||||||
|
|
||||||
|
anteDecorators := []sdk.AnteDecorator{
|
||||||
|
NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
|
||||||
|
NewRejectExtensionOptionsDecorator(),
|
||||||
|
NewMempoolFeeDecorator(),
|
||||||
|
NewValidateBasicDecorator(),
|
||||||
|
NewTxTimeoutHeightDecorator(),
|
||||||
|
NewValidateMemoDecorator(options.AccountKeeper),
|
||||||
|
NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
|
||||||
|
NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper),
|
||||||
|
NewSetPubKeyDecorator(options.AccountKeeper), // SetPubKeyDecorator must be called before all signature verification decorators
|
||||||
|
NewValidateSigCountDecorator(options.AccountKeeper),
|
||||||
|
NewSigGasConsumeDecorator(options.AccountKeeper, sigGasConsumer),
|
||||||
|
NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
|
||||||
|
NewIncrementSequenceDecorator(options.AccountKeeper),
|
||||||
|
}
|
||||||
|
|
||||||
|
return sdk.ChainAnteDecorators(anteDecorators...), nil
|
||||||
|
}
|
1151
x/auth/ante/ante_test.go
Normal file
1151
x/auth/ante/ante_test.go
Normal file
File diff suppressed because it is too large
Load Diff
206
x/auth/ante/basic.go
Normal file
206
x/auth/ante/basic.go
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
package ante
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec/legacy"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
|
||||||
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
|
||||||
|
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ValidateBasicDecorator will call tx.ValidateBasic and return any non-nil error.
|
||||||
|
// If ValidateBasic passes, decorator calls next AnteHandler in chain. Note,
|
||||||
|
// ValidateBasicDecorator decorator will not get executed on ReCheckTx since it
|
||||||
|
// is not dependent on application state.
|
||||||
|
type ValidateBasicDecorator struct{}
|
||||||
|
|
||||||
|
func NewValidateBasicDecorator() ValidateBasicDecorator {
|
||||||
|
return ValidateBasicDecorator{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vbd ValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||||
|
// no need to validate basic on recheck tx, call next antehandler
|
||||||
|
if ctx.IsReCheckTx() {
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.ValidateBasic(); err != nil {
|
||||||
|
return ctx, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateMemoDecorator will validate memo given the parameters passed in
|
||||||
|
// If memo is too large decorator returns with error, otherwise call next AnteHandler
|
||||||
|
// CONTRACT: Tx must implement TxWithMemo interface
|
||||||
|
type ValidateMemoDecorator struct {
|
||||||
|
ak AccountKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewValidateMemoDecorator(ak AccountKeeper) ValidateMemoDecorator {
|
||||||
|
return ValidateMemoDecorator{
|
||||||
|
ak: ak,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vmd ValidateMemoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||||
|
memoTx, ok := tx.(sdk.TxWithMemo)
|
||||||
|
if !ok {
|
||||||
|
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
|
||||||
|
}
|
||||||
|
|
||||||
|
params := vmd.ak.GetParams(ctx)
|
||||||
|
|
||||||
|
memoLength := len(memoTx.GetMemo())
|
||||||
|
if uint64(memoLength) > params.MaxMemoCharacters {
|
||||||
|
return ctx, sdkerrors.Wrapf(sdkerrors.ErrMemoTooLarge,
|
||||||
|
"maximum number of characters is %d but received %d characters",
|
||||||
|
params.MaxMemoCharacters, memoLength,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConsumeTxSizeGasDecorator will take in parameters and consume gas proportional
|
||||||
|
// to the size of tx before calling next AnteHandler. Note, the gas costs will be
|
||||||
|
// slightly over estimated due to the fact that any given signing account may need
|
||||||
|
// to be retrieved from state.
|
||||||
|
//
|
||||||
|
// CONTRACT: If simulate=true, then signatures must either be completely filled
|
||||||
|
// in or empty.
|
||||||
|
// CONTRACT: To use this decorator, signatures of transaction must be represented
|
||||||
|
// as legacytx.StdSignature otherwise simulate mode will incorrectly estimate gas cost.
|
||||||
|
type ConsumeTxSizeGasDecorator struct {
|
||||||
|
ak AccountKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConsumeGasForTxSizeDecorator(ak AccountKeeper) ConsumeTxSizeGasDecorator {
|
||||||
|
return ConsumeTxSizeGasDecorator{
|
||||||
|
ak: ak,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||||
|
sigTx, ok := tx.(authsigning.SigVerifiableTx)
|
||||||
|
if !ok {
|
||||||
|
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid tx type")
|
||||||
|
}
|
||||||
|
params := cgts.ak.GetParams(ctx)
|
||||||
|
|
||||||
|
ctx.GasMeter().ConsumeGas(params.TxSizeCostPerByte*sdk.Gas(len(ctx.TxBytes())), "txSize")
|
||||||
|
|
||||||
|
// simulate gas cost for signatures in simulate mode
|
||||||
|
if simulate {
|
||||||
|
// in simulate mode, each element should be a nil signature
|
||||||
|
sigs, err := sigTx.GetSignaturesV2()
|
||||||
|
if err != nil {
|
||||||
|
return ctx, err
|
||||||
|
}
|
||||||
|
n := len(sigs)
|
||||||
|
|
||||||
|
for i, signer := range sigTx.GetSigners() {
|
||||||
|
// if signature is already filled in, no need to simulate gas cost
|
||||||
|
if i < n && !isIncompleteSignature(sigs[i].Data) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var pubkey cryptotypes.PubKey
|
||||||
|
|
||||||
|
acc := cgts.ak.GetAccount(ctx, signer)
|
||||||
|
|
||||||
|
// use placeholder simSecp256k1Pubkey if sig is nil
|
||||||
|
if acc == nil || acc.GetPubKey() == nil {
|
||||||
|
pubkey = simSecp256k1Pubkey
|
||||||
|
} else {
|
||||||
|
pubkey = acc.GetPubKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
// use stdsignature to mock the size of a full signature
|
||||||
|
simSig := legacytx.StdSignature{ //nolint:staticcheck // this will be removed when proto is ready
|
||||||
|
Signature: simSecp256k1Sig[:],
|
||||||
|
PubKey: pubkey,
|
||||||
|
}
|
||||||
|
|
||||||
|
sigBz := legacy.Cdc.MustMarshal(simSig)
|
||||||
|
cost := sdk.Gas(len(sigBz) + 6)
|
||||||
|
|
||||||
|
// If the pubkey is a multi-signature pubkey, then we estimate for the maximum
|
||||||
|
// number of signers.
|
||||||
|
if _, ok := pubkey.(*multisig.LegacyAminoPubKey); ok {
|
||||||
|
cost *= params.TxSigLimit
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.GasMeter().ConsumeGas(params.TxSizeCostPerByte*cost, "txSize")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// isIncompleteSignature tests whether SignatureData is fully filled in for simulation purposes
|
||||||
|
func isIncompleteSignature(data signing.SignatureData) bool {
|
||||||
|
if data == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
switch data := data.(type) {
|
||||||
|
case *signing.SingleSignatureData:
|
||||||
|
return len(data.Signature) == 0
|
||||||
|
case *signing.MultiSignatureData:
|
||||||
|
if len(data.Signatures) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for _, s := range data.Signatures {
|
||||||
|
if isIncompleteSignature(s) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
// TxTimeoutHeightDecorator defines an AnteHandler decorator that checks for a
|
||||||
|
// tx height timeout.
|
||||||
|
TxTimeoutHeightDecorator struct{}
|
||||||
|
|
||||||
|
// TxWithTimeoutHeight defines the interface a tx must implement in order for
|
||||||
|
// TxHeightTimeoutDecorator to process the tx.
|
||||||
|
TxWithTimeoutHeight interface {
|
||||||
|
sdk.Tx
|
||||||
|
|
||||||
|
GetTimeoutHeight() uint64
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// TxTimeoutHeightDecorator defines an AnteHandler decorator that checks for a
|
||||||
|
// tx height timeout.
|
||||||
|
func NewTxTimeoutHeightDecorator() TxTimeoutHeightDecorator {
|
||||||
|
return TxTimeoutHeightDecorator{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnteHandle implements an AnteHandler decorator for the TxHeightTimeoutDecorator
|
||||||
|
// type where the current block height is checked against the tx's height timeout.
|
||||||
|
// If a height timeout is provided (non-zero) and is less than the current block
|
||||||
|
// height, then an error is returned.
|
||||||
|
func (txh TxTimeoutHeightDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||||
|
timeoutTx, ok := tx.(TxWithTimeoutHeight)
|
||||||
|
if !ok {
|
||||||
|
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "expected tx to implement TxWithTimeoutHeight")
|
||||||
|
}
|
||||||
|
|
||||||
|
timeoutHeight := timeoutTx.GetTimeoutHeight()
|
||||||
|
if timeoutHeight > 0 && uint64(ctx.BlockHeight()) > timeoutHeight {
|
||||||
|
return ctx, sdkerrors.Wrapf(
|
||||||
|
sdkerrors.ErrTxTimeoutHeight, "block height: %d, timeout height: %d", ctx.BlockHeight(), timeoutHeight,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
224
x/auth/ante/basic_test.go
Normal file
224
x/auth/ante/basic_test.go
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
package ante_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||||
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) TestValidateBasic() {
|
||||||
|
suite.SetupTest(true) // setup
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||||
|
|
||||||
|
// keys and addresses
|
||||||
|
priv1, _, addr1 := testdata.KeyTestPubAddr()
|
||||||
|
|
||||||
|
// msg and signatures
|
||||||
|
msg := testdata.NewTestMsg(addr1)
|
||||||
|
feeAmount := testdata.NewTestFeeAmount()
|
||||||
|
gasLimit := testdata.NewTestGasLimit()
|
||||||
|
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
|
||||||
|
suite.txBuilder.SetFeeAmount(feeAmount)
|
||||||
|
suite.txBuilder.SetGasLimit(gasLimit)
|
||||||
|
|
||||||
|
privs, accNums, accSeqs := []cryptotypes.PrivKey{}, []uint64{}, []uint64{}
|
||||||
|
invalidTx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
vbd := ante.NewValidateBasicDecorator()
|
||||||
|
antehandler := sdk.ChainAnteDecorators(vbd)
|
||||||
|
_, err = antehandler(suite.ctx, invalidTx, false)
|
||||||
|
|
||||||
|
suite.Require().NotNil(err, "Did not error on invalid tx")
|
||||||
|
|
||||||
|
privs, accNums, accSeqs = []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
|
||||||
|
validTx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
_, err = antehandler(suite.ctx, validTx, false)
|
||||||
|
suite.Require().Nil(err, "ValidateBasicDecorator returned error on valid tx. err: %v", err)
|
||||||
|
|
||||||
|
// test decorator skips on recheck
|
||||||
|
suite.ctx = suite.ctx.WithIsReCheckTx(true)
|
||||||
|
|
||||||
|
// decorator should skip processing invalidTx on recheck and thus return nil-error
|
||||||
|
_, err = antehandler(suite.ctx, invalidTx, false)
|
||||||
|
|
||||||
|
suite.Require().Nil(err, "ValidateBasicDecorator ran on ReCheck")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) TestValidateMemo() {
|
||||||
|
suite.SetupTest(true) // setup
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||||
|
|
||||||
|
// keys and addresses
|
||||||
|
priv1, _, addr1 := testdata.KeyTestPubAddr()
|
||||||
|
|
||||||
|
// msg and signatures
|
||||||
|
msg := testdata.NewTestMsg(addr1)
|
||||||
|
feeAmount := testdata.NewTestFeeAmount()
|
||||||
|
gasLimit := testdata.NewTestGasLimit()
|
||||||
|
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
|
||||||
|
suite.txBuilder.SetFeeAmount(feeAmount)
|
||||||
|
suite.txBuilder.SetGasLimit(gasLimit)
|
||||||
|
|
||||||
|
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
|
||||||
|
suite.txBuilder.SetMemo(strings.Repeat("01234567890", 500))
|
||||||
|
invalidTx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
// require that long memos get rejected
|
||||||
|
vmd := ante.NewValidateMemoDecorator(suite.app.AccountKeeper)
|
||||||
|
antehandler := sdk.ChainAnteDecorators(vmd)
|
||||||
|
_, err = antehandler(suite.ctx, invalidTx, false)
|
||||||
|
|
||||||
|
suite.Require().NotNil(err, "Did not error on tx with high memo")
|
||||||
|
|
||||||
|
suite.txBuilder.SetMemo(strings.Repeat("01234567890", 10))
|
||||||
|
validTx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
// require small memos pass ValidateMemo Decorator
|
||||||
|
_, err = antehandler(suite.ctx, validTx, false)
|
||||||
|
suite.Require().Nil(err, "ValidateBasicDecorator returned error on valid tx. err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) TestConsumeGasForTxSize() {
|
||||||
|
suite.SetupTest(true) // setup
|
||||||
|
|
||||||
|
// keys and addresses
|
||||||
|
priv1, _, addr1 := testdata.KeyTestPubAddr()
|
||||||
|
|
||||||
|
// msg and signatures
|
||||||
|
msg := testdata.NewTestMsg(addr1)
|
||||||
|
feeAmount := testdata.NewTestFeeAmount()
|
||||||
|
gasLimit := testdata.NewTestGasLimit()
|
||||||
|
|
||||||
|
cgtsd := ante.NewConsumeGasForTxSizeDecorator(suite.app.AccountKeeper)
|
||||||
|
antehandler := sdk.ChainAnteDecorators(cgtsd)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
sigV2 signing.SignatureV2
|
||||||
|
}{
|
||||||
|
{"SingleSignatureData", signing.SignatureV2{PubKey: priv1.PubKey()}},
|
||||||
|
{"MultiSignatureData", signing.SignatureV2{PubKey: priv1.PubKey(), Data: multisig.NewMultisig(2)}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||||
|
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
|
||||||
|
suite.txBuilder.SetFeeAmount(feeAmount)
|
||||||
|
suite.txBuilder.SetGasLimit(gasLimit)
|
||||||
|
suite.txBuilder.SetMemo(strings.Repeat("01234567890", 10))
|
||||||
|
|
||||||
|
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
|
||||||
|
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
txBytes, err := suite.clientCtx.TxConfig.TxJSONEncoder()(tx)
|
||||||
|
suite.Require().Nil(err, "Cannot marshal tx: %v", err)
|
||||||
|
|
||||||
|
params := suite.app.AccountKeeper.GetParams(suite.ctx)
|
||||||
|
expectedGas := sdk.Gas(len(txBytes)) * params.TxSizeCostPerByte
|
||||||
|
|
||||||
|
// Set suite.ctx with TxBytes manually
|
||||||
|
suite.ctx = suite.ctx.WithTxBytes(txBytes)
|
||||||
|
|
||||||
|
// track how much gas is necessary to retrieve parameters
|
||||||
|
beforeGas := suite.ctx.GasMeter().GasConsumed()
|
||||||
|
suite.app.AccountKeeper.GetParams(suite.ctx)
|
||||||
|
afterGas := suite.ctx.GasMeter().GasConsumed()
|
||||||
|
expectedGas += afterGas - beforeGas
|
||||||
|
|
||||||
|
beforeGas = suite.ctx.GasMeter().GasConsumed()
|
||||||
|
suite.ctx, err = antehandler(suite.ctx, tx, false)
|
||||||
|
suite.Require().Nil(err, "ConsumeTxSizeGasDecorator returned error: %v", err)
|
||||||
|
|
||||||
|
// require that decorator consumes expected amount of gas
|
||||||
|
consumedGas := suite.ctx.GasMeter().GasConsumed() - beforeGas
|
||||||
|
suite.Require().Equal(expectedGas, consumedGas, "Decorator did not consume the correct amount of gas")
|
||||||
|
|
||||||
|
// simulation must not underestimate gas of this decorator even with nil signatures
|
||||||
|
txBuilder, err := suite.clientCtx.TxConfig.WrapTxBuilder(tx)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Require().NoError(txBuilder.SetSignatures(tc.sigV2))
|
||||||
|
tx = txBuilder.GetTx()
|
||||||
|
|
||||||
|
simTxBytes, err := suite.clientCtx.TxConfig.TxJSONEncoder()(tx)
|
||||||
|
suite.Require().Nil(err, "Cannot marshal tx: %v", err)
|
||||||
|
// require that simulated tx is smaller than tx with signatures
|
||||||
|
suite.Require().True(len(simTxBytes) < len(txBytes), "simulated tx still has signatures")
|
||||||
|
|
||||||
|
// Set suite.ctx with smaller simulated TxBytes manually
|
||||||
|
suite.ctx = suite.ctx.WithTxBytes(simTxBytes)
|
||||||
|
|
||||||
|
beforeSimGas := suite.ctx.GasMeter().GasConsumed()
|
||||||
|
|
||||||
|
// run antehandler with simulate=true
|
||||||
|
suite.ctx, err = antehandler(suite.ctx, tx, true)
|
||||||
|
consumedSimGas := suite.ctx.GasMeter().GasConsumed() - beforeSimGas
|
||||||
|
|
||||||
|
// require that antehandler passes and does not underestimate decorator cost
|
||||||
|
suite.Require().Nil(err, "ConsumeTxSizeGasDecorator returned error: %v", err)
|
||||||
|
suite.Require().True(consumedSimGas >= expectedGas, "Simulate mode underestimates gas on AnteDecorator. Simulated cost: %d, expected cost: %d", consumedSimGas, expectedGas)
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) TestTxHeightTimeoutDecorator() {
|
||||||
|
suite.SetupTest(true)
|
||||||
|
|
||||||
|
antehandler := sdk.ChainAnteDecorators(ante.NewTxTimeoutHeightDecorator())
|
||||||
|
|
||||||
|
// keys and addresses
|
||||||
|
priv1, _, addr1 := testdata.KeyTestPubAddr()
|
||||||
|
|
||||||
|
// msg and signatures
|
||||||
|
msg := testdata.NewTestMsg(addr1)
|
||||||
|
feeAmount := testdata.NewTestFeeAmount()
|
||||||
|
gasLimit := testdata.NewTestGasLimit()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
timeout uint64
|
||||||
|
height int64
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{"default value", 0, 10, false},
|
||||||
|
{"no timeout (greater height)", 15, 10, false},
|
||||||
|
{"no timeout (same height)", 10, 10, false},
|
||||||
|
{"timeout (smaller height)", 9, 10, true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
tc := tc
|
||||||
|
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||||
|
|
||||||
|
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
|
||||||
|
|
||||||
|
suite.txBuilder.SetFeeAmount(feeAmount)
|
||||||
|
suite.txBuilder.SetGasLimit(gasLimit)
|
||||||
|
suite.txBuilder.SetMemo(strings.Repeat("01234567890", 10))
|
||||||
|
suite.txBuilder.SetTimeoutHeight(tc.timeout)
|
||||||
|
|
||||||
|
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
|
||||||
|
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
ctx := suite.ctx.WithBlockHeight(tc.height)
|
||||||
|
_, err = antehandler(ctx, tx, true)
|
||||||
|
suite.Require().Equal(tc.expectErr, err != nil, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
20
x/auth/ante/expected_keepers.go
Normal file
20
x/auth/ante/expected_keepers.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package ante
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/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 types.Params)
|
||||||
|
GetAccount(ctx sdk.Context, addr sdk.AccAddress) types.AccountI
|
||||||
|
SetAccount(ctx sdk.Context, acc types.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
|
||||||
|
}
|
36
x/auth/ante/ext.go
Normal file
36
x/auth/ante/ext.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package ante
|
||||||
|
|
||||||
|
import (
|
||||||
|
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types"
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HasExtensionOptionsTx interface {
|
||||||
|
GetExtensionOptions() []*codectypes.Any
|
||||||
|
GetNonCriticalExtensionOptions() []*codectypes.Any
|
||||||
|
}
|
||||||
|
|
||||||
|
// RejectExtensionOptionsDecorator is an AnteDecorator that rejects all extension
|
||||||
|
// options which can optionally be included in protobuf transactions. Users that
|
||||||
|
// need extension options should create a custom AnteHandler chain that handles
|
||||||
|
// needed extension options properly and rejects unknown ones.
|
||||||
|
type RejectExtensionOptionsDecorator struct{}
|
||||||
|
|
||||||
|
// NewRejectExtensionOptionsDecorator creates a new RejectExtensionOptionsDecorator
|
||||||
|
func NewRejectExtensionOptionsDecorator() RejectExtensionOptionsDecorator {
|
||||||
|
return RejectExtensionOptionsDecorator{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ types.AnteDecorator = RejectExtensionOptionsDecorator{}
|
||||||
|
|
||||||
|
// AnteHandle implements the AnteDecorator.AnteHandle method
|
||||||
|
func (r RejectExtensionOptionsDecorator) AnteHandle(ctx types.Context, tx types.Tx, simulate bool, next types.AnteHandler) (newCtx types.Context, err error) {
|
||||||
|
if hasExtOptsTx, ok := tx.(HasExtensionOptionsTx); ok {
|
||||||
|
if len(hasExtOptsTx.GetExtensionOptions()) != 0 {
|
||||||
|
return ctx, sdkerrors.ErrUnknownExtensionOptions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
36
x/auth/ante/ext_test.go
Normal file
36
x/auth/ante/ext_test.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package ante_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) TestRejectExtensionOptionsDecorator() {
|
||||||
|
suite.SetupTest(true) // setup
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||||
|
|
||||||
|
reod := ante.NewRejectExtensionOptionsDecorator()
|
||||||
|
antehandler := sdk.ChainAnteDecorators(reod)
|
||||||
|
|
||||||
|
// no extension options should not trigger an error
|
||||||
|
theTx := suite.txBuilder.GetTx()
|
||||||
|
_, err := antehandler(suite.ctx, theTx, false)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
extOptsTxBldr, ok := suite.txBuilder.(tx.ExtensionOptionsTxBuilder)
|
||||||
|
if !ok {
|
||||||
|
// if we can't set extension options, this decorator doesn't apply and we're done
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// setting any extension option should cause an error
|
||||||
|
any, err := types.NewAnyWithValue(testdata.NewTestMsg())
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
extOptsTxBldr.SetExtensionOptions(any)
|
||||||
|
theTx = suite.txBuilder.GetTx()
|
||||||
|
_, err = antehandler(suite.ctx, theTx, false)
|
||||||
|
suite.Require().EqualError(err, "unknown extension options")
|
||||||
|
}
|
141
x/auth/ante/fee.go
Normal file
141
x/auth/ante/fee.go
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package ante
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||||
|
|
||||||
|
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 := feeTx.GetFee()
|
||||||
|
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 evmtypes.BankKeeper
|
||||||
|
feegrantKeeper FeegrantKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDeductFeeDecorator(ak AccountKeeper, bk evmtypes.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 {
|
||||||
|
panic(fmt.Sprintf("%s module account has not been set", types.FeeCollectorName))
|
||||||
|
}
|
||||||
|
|
||||||
|
fee := feeTx.GetFee()
|
||||||
|
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 !feeTx.GetFee().IsZero() {
|
||||||
|
err = DeductFees(dfd.bankKeeper, ctx, deductFeesFromAcc, feeTx.GetFee())
|
||||||
|
if err != nil {
|
||||||
|
return ctx, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
events := sdk.Events{sdk.NewEvent(sdk.EventTypeTx,
|
||||||
|
sdk.NewAttribute(sdk.AttributeKeyFee, feeTx.GetFee().String()),
|
||||||
|
)}
|
||||||
|
ctx.EventManager().EmitEvents(events)
|
||||||
|
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeductFees deducts fees from the given account.
|
||||||
|
func DeductFees(bankKeeper evmtypes.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
|
||||||
|
}
|
104
x/auth/ante/fee_test.go
Normal file
104
x/auth/ante/fee_test.go
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package ante_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) TestEnsureMempoolFees() {
|
||||||
|
suite.SetupTest(true) // setup
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||||
|
|
||||||
|
mfd := ante.NewMempoolFeeDecorator()
|
||||||
|
antehandler := sdk.ChainAnteDecorators(mfd)
|
||||||
|
|
||||||
|
// keys and addresses
|
||||||
|
priv1, _, addr1 := testdata.KeyTestPubAddr()
|
||||||
|
|
||||||
|
// msg and signatures
|
||||||
|
msg := testdata.NewTestMsg(addr1)
|
||||||
|
feeAmount := testdata.NewTestFeeAmount()
|
||||||
|
gasLimit := testdata.NewTestGasLimit()
|
||||||
|
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
|
||||||
|
suite.txBuilder.SetFeeAmount(feeAmount)
|
||||||
|
suite.txBuilder.SetGasLimit(gasLimit)
|
||||||
|
|
||||||
|
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
|
||||||
|
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
// Set high gas price so standard test fee fails
|
||||||
|
atomPrice := sdk.NewDecCoinFromDec("atom", sdk.NewDec(200).Quo(sdk.NewDec(100000)))
|
||||||
|
highGasPrice := []sdk.DecCoin{atomPrice}
|
||||||
|
suite.ctx = suite.ctx.WithMinGasPrices(highGasPrice)
|
||||||
|
|
||||||
|
// Set IsCheckTx to true
|
||||||
|
suite.ctx = suite.ctx.WithIsCheckTx(true)
|
||||||
|
|
||||||
|
// antehandler errors with insufficient fees
|
||||||
|
_, err = antehandler(suite.ctx, tx, false)
|
||||||
|
suite.Require().NotNil(err, "Decorator should have errored on too low fee for local gasPrice")
|
||||||
|
|
||||||
|
// Set IsCheckTx to false
|
||||||
|
suite.ctx = suite.ctx.WithIsCheckTx(false)
|
||||||
|
|
||||||
|
// antehandler should not error since we do not check minGasPrice in DeliverTx
|
||||||
|
_, err = antehandler(suite.ctx, tx, false)
|
||||||
|
suite.Require().Nil(err, "MempoolFeeDecorator returned error in DeliverTx")
|
||||||
|
|
||||||
|
// Set IsCheckTx back to true for testing sufficient mempool fee
|
||||||
|
suite.ctx = suite.ctx.WithIsCheckTx(true)
|
||||||
|
|
||||||
|
atomPrice = sdk.NewDecCoinFromDec("atom", sdk.NewDec(0).Quo(sdk.NewDec(100000)))
|
||||||
|
lowGasPrice := []sdk.DecCoin{atomPrice}
|
||||||
|
suite.ctx = suite.ctx.WithMinGasPrices(lowGasPrice)
|
||||||
|
|
||||||
|
_, err = antehandler(suite.ctx, tx, false)
|
||||||
|
suite.Require().Nil(err, "Decorator should not have errored on fee higher than local gasPrice")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) TestDeductFees() {
|
||||||
|
suite.SetupTest(false) // setup
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||||
|
|
||||||
|
// keys and addresses
|
||||||
|
priv1, _, addr1 := testdata.KeyTestPubAddr()
|
||||||
|
|
||||||
|
// msg and signatures
|
||||||
|
msg := testdata.NewTestMsg(addr1)
|
||||||
|
feeAmount := testdata.NewTestFeeAmount()
|
||||||
|
gasLimit := testdata.NewTestGasLimit()
|
||||||
|
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
|
||||||
|
suite.txBuilder.SetFeeAmount(feeAmount)
|
||||||
|
suite.txBuilder.SetGasLimit(gasLimit)
|
||||||
|
|
||||||
|
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
|
||||||
|
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
// Set account with insufficient funds
|
||||||
|
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||||
|
coins := sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(10)))
|
||||||
|
err = simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr1, coins)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
dfd := ante.NewDeductFeeDecorator(suite.app.AccountKeeper, suite.app.BankKeeper, nil)
|
||||||
|
antehandler := sdk.ChainAnteDecorators(dfd)
|
||||||
|
|
||||||
|
_, err = antehandler(suite.ctx, tx, false)
|
||||||
|
|
||||||
|
suite.Require().NotNil(err, "Tx did not error when fee payer had insufficient funds")
|
||||||
|
|
||||||
|
// Set account with sufficient funds
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||||
|
err = simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr1, sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(200))))
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
_, err = antehandler(suite.ctx, tx, false)
|
||||||
|
|
||||||
|
suite.Require().Nil(err, "Tx errored after account has been set with sufficient funds")
|
||||||
|
}
|
233
x/auth/ante/feegrant_test.go
Normal file
233
x/auth/ante/feegrant_test.go
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
package ante_test
|
||||||
|
|
||||||
|
/* TODO: fix these tests
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tendermint/tendermint/crypto"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
|
"github.com/cosmos/cosmos-sdk/simapp/helpers"
|
||||||
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/simulation"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
|
ante "github.com/tharsis/ethermint/x/auth/ante"
|
||||||
|
authsign "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||||
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/feegrant"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) TestDeductFeesNoDelegation() {
|
||||||
|
suite.SetupTest(false)
|
||||||
|
// setup
|
||||||
|
app, ctx := suite.app, suite.ctx
|
||||||
|
|
||||||
|
protoTxCfg := tx.NewTxConfig(codec.NewProtoCodec(app.InterfaceRegistry()), tx.DefaultSignModes)
|
||||||
|
|
||||||
|
// this just tests our handler
|
||||||
|
dfd := ante.NewDeductFeeDecorator(app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper)
|
||||||
|
feeAnteHandler := sdk.ChainAnteDecorators(dfd)
|
||||||
|
|
||||||
|
// this tests the whole stack
|
||||||
|
anteHandlerStack := suite.anteHandler
|
||||||
|
|
||||||
|
// keys and addresses
|
||||||
|
priv1, _, addr1 := testdata.KeyTestPubAddr()
|
||||||
|
priv2, _, addr2 := testdata.KeyTestPubAddr()
|
||||||
|
priv3, _, addr3 := testdata.KeyTestPubAddr()
|
||||||
|
priv4, _, addr4 := testdata.KeyTestPubAddr()
|
||||||
|
priv5, _, addr5 := testdata.KeyTestPubAddr()
|
||||||
|
|
||||||
|
// Set addr1 with insufficient funds
|
||||||
|
err := simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr1, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(10))})
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
// Set addr2 with more funds
|
||||||
|
err = simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr2, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(99999))})
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
// grant fee allowance from `addr2` to `addr3` (plenty to pay)
|
||||||
|
err = app.FeeGrantKeeper.GrantAllowance(ctx, addr2, addr3, &feegrant.BasicAllowance{
|
||||||
|
SpendLimit: sdk.NewCoins(sdk.NewInt64Coin("atom", 500)),
|
||||||
|
})
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
// grant low fee allowance (20atom), to check the tx requesting more than allowed.
|
||||||
|
err = app.FeeGrantKeeper.GrantAllowance(ctx, addr2, addr4, &feegrant.BasicAllowance{
|
||||||
|
SpendLimit: sdk.NewCoins(sdk.NewInt64Coin("atom", 20)),
|
||||||
|
})
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
cases := map[string]struct {
|
||||||
|
signerKey cryptotypes.PrivKey
|
||||||
|
signer sdk.AccAddress
|
||||||
|
feeAccount sdk.AccAddress
|
||||||
|
fee int64
|
||||||
|
valid bool
|
||||||
|
}{
|
||||||
|
"paying with low funds": {
|
||||||
|
signerKey: priv1,
|
||||||
|
signer: addr1,
|
||||||
|
fee: 50,
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
"paying with good funds": {
|
||||||
|
signerKey: priv2,
|
||||||
|
signer: addr2,
|
||||||
|
fee: 50,
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
"paying with no account": {
|
||||||
|
signerKey: priv3,
|
||||||
|
signer: addr3,
|
||||||
|
fee: 1,
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
"no fee with real account": {
|
||||||
|
signerKey: priv1,
|
||||||
|
signer: addr1,
|
||||||
|
fee: 0,
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
"no fee with no account": {
|
||||||
|
signerKey: priv5,
|
||||||
|
signer: addr5,
|
||||||
|
fee: 0,
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
"valid fee grant without account": {
|
||||||
|
signerKey: priv3,
|
||||||
|
signer: addr3,
|
||||||
|
feeAccount: addr2,
|
||||||
|
fee: 50,
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
"no fee grant": {
|
||||||
|
signerKey: priv3,
|
||||||
|
signer: addr3,
|
||||||
|
feeAccount: addr1,
|
||||||
|
fee: 2,
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
"allowance smaller than requested fee": {
|
||||||
|
signerKey: priv4,
|
||||||
|
signer: addr4,
|
||||||
|
feeAccount: addr2,
|
||||||
|
fee: 50,
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
"granter cannot cover allowed fee grant": {
|
||||||
|
signerKey: priv4,
|
||||||
|
signer: addr4,
|
||||||
|
feeAccount: addr1,
|
||||||
|
fee: 50,
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, stc := range cases {
|
||||||
|
tc := stc // to make scopelint happy
|
||||||
|
suite.T().Run(name, func(t *testing.T) {
|
||||||
|
fee := sdk.NewCoins(sdk.NewInt64Coin("atom", tc.fee))
|
||||||
|
msgs := []sdk.Msg{testdata.NewTestMsg(tc.signer)}
|
||||||
|
|
||||||
|
acc := app.AccountKeeper.GetAccount(ctx, tc.signer)
|
||||||
|
privs, accNums, seqs := []cryptotypes.PrivKey{tc.signerKey}, []uint64{0}, []uint64{0}
|
||||||
|
if acc != nil {
|
||||||
|
accNums, seqs = []uint64{acc.GetAccountNumber()}, []uint64{acc.GetSequence()}
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := genTxWithFeeGranter(protoTxCfg, msgs, fee, helpers.DefaultGenTxGas, ctx.ChainID(), accNums, seqs, tc.feeAccount, privs...)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
_, err = feeAnteHandler(ctx, tx, false) // tests only feegrant ante
|
||||||
|
if tc.valid {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = anteHandlerStack(ctx, tx, false) // tests while stack
|
||||||
|
if tc.valid {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't consume any gas
|
||||||
|
func SigGasNoConsumer(meter sdk.GasMeter, sig []byte, pubkey crypto.PubKey, params authtypes.Params) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func genTxWithFeeGranter(gen client.TxConfig, msgs []sdk.Msg, feeAmt sdk.Coins, gas uint64, chainID string, accNums,
|
||||||
|
accSeqs []uint64, feeGranter sdk.AccAddress, priv ...cryptotypes.PrivKey) (sdk.Tx, error) {
|
||||||
|
sigs := make([]signing.SignatureV2, len(priv))
|
||||||
|
|
||||||
|
// create a random length memo
|
||||||
|
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
|
||||||
|
memo := simulation.RandStringOfLength(r, simulation.RandIntBetween(r, 0, 100))
|
||||||
|
|
||||||
|
signMode := gen.SignModeHandler().DefaultMode()
|
||||||
|
|
||||||
|
// 1st round: set SignatureV2 with empty signatures, to set correct
|
||||||
|
// signer infos.
|
||||||
|
for i, p := range priv {
|
||||||
|
sigs[i] = signing.SignatureV2{
|
||||||
|
PubKey: p.PubKey(),
|
||||||
|
Data: &signing.SingleSignatureData{
|
||||||
|
SignMode: signMode,
|
||||||
|
},
|
||||||
|
Sequence: accSeqs[i],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tx := gen.NewTxBuilder()
|
||||||
|
err := tx.SetMsgs(msgs...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = tx.SetSignatures(sigs...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tx.SetMemo(memo)
|
||||||
|
tx.SetFeeAmount(feeAmt)
|
||||||
|
tx.SetGasLimit(gas)
|
||||||
|
tx.SetFeeGranter(feeGranter)
|
||||||
|
|
||||||
|
// 2nd round: once all signer infos are set, every signer can sign.
|
||||||
|
for i, p := range priv {
|
||||||
|
signerData := authsign.SignerData{
|
||||||
|
ChainID: chainID,
|
||||||
|
AccountNumber: accNums[i],
|
||||||
|
Sequence: accSeqs[i],
|
||||||
|
}
|
||||||
|
signBytes, err := gen.SignModeHandler().GetSignBytes(signMode, signerData, tx.GetTx())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
sig, err := p.Sign(signBytes)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
sigs[i].Data.(*signing.SingleSignatureData).Signature = sig
|
||||||
|
err = tx.SetSignatures(sigs...)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.GetTx(), nil
|
||||||
|
}
|
||||||
|
*/
|
76
x/auth/ante/setup.go
Normal file
76
x/auth/ante/setup.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
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/legacy/legacytx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ GasTx = (*legacytx.StdTx)(nil) // assert StdTx implements GasTx
|
||||||
|
)
|
||||||
|
|
||||||
|
// GasTx defines a Tx with a GetGas() method which is needed to use SetUpContextDecorator
|
||||||
|
type GasTx interface {
|
||||||
|
sdk.Tx
|
||||||
|
GetGas() uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUpContextDecorator sets the GasMeter in the Context and wraps the next AnteHandler with a defer clause
|
||||||
|
// to recover from any downstream OutOfGas panics in the AnteHandler chain to return an error with information
|
||||||
|
// on gas provided and gas used.
|
||||||
|
// CONTRACT: Must be first decorator in the chain
|
||||||
|
// CONTRACT: Tx must implement GasTx interface
|
||||||
|
type SetUpContextDecorator struct{}
|
||||||
|
|
||||||
|
func NewSetUpContextDecorator() SetUpContextDecorator {
|
||||||
|
return SetUpContextDecorator{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sud SetUpContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||||
|
// all transactions must implement GasTx
|
||||||
|
gasTx, ok := tx.(GasTx)
|
||||||
|
if !ok {
|
||||||
|
// Set a gas meter with limit 0 as to prevent an infinite gas meter attack
|
||||||
|
// during runTx.
|
||||||
|
newCtx = SetGasMeter(simulate, ctx, 0)
|
||||||
|
return newCtx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be GasTx")
|
||||||
|
}
|
||||||
|
|
||||||
|
newCtx = SetGasMeter(simulate, ctx, gasTx.GetGas())
|
||||||
|
|
||||||
|
// Decorator will catch an OutOfGasPanic caused in the next antehandler
|
||||||
|
// AnteHandlers must have their own defer/recover in order for the BaseApp
|
||||||
|
// to know how much gas was used! This is because the GasMeter is created in
|
||||||
|
// the AnteHandler, but if it panics the context won't be set properly in
|
||||||
|
// runTx's recover call.
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
switch rType := r.(type) {
|
||||||
|
case sdk.ErrorOutOfGas:
|
||||||
|
log := fmt.Sprintf(
|
||||||
|
"out of gas in location: %v; gasWanted: %d, gasUsed: %d",
|
||||||
|
rType.Descriptor, gasTx.GetGas(), newCtx.GasMeter().GasConsumed())
|
||||||
|
|
||||||
|
err = sdkerrors.Wrap(sdkerrors.ErrOutOfGas, log)
|
||||||
|
default:
|
||||||
|
panic(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return next(newCtx, tx, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetGasMeter returns a new context with a gas meter set from a given context.
|
||||||
|
func SetGasMeter(simulate bool, ctx sdk.Context, gasLimit uint64) sdk.Context {
|
||||||
|
// In various cases such as simulation and during the genesis block, we do not
|
||||||
|
// meter any gas utilization.
|
||||||
|
if simulate || ctx.BlockHeight() == 0 {
|
||||||
|
return ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.WithGasMeter(sdk.NewGasMeter(gasLimit))
|
||||||
|
}
|
99
x/auth/ante/setup_test.go
Normal file
99
x/auth/ante/setup_test.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package ante_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) TestSetup() {
|
||||||
|
suite.SetupTest(true) // setup
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||||
|
|
||||||
|
// keys and addresses
|
||||||
|
priv1, _, addr1 := testdata.KeyTestPubAddr()
|
||||||
|
|
||||||
|
// msg and signatures
|
||||||
|
msg := testdata.NewTestMsg(addr1)
|
||||||
|
feeAmount := testdata.NewTestFeeAmount()
|
||||||
|
gasLimit := testdata.NewTestGasLimit()
|
||||||
|
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
|
||||||
|
suite.txBuilder.SetFeeAmount(feeAmount)
|
||||||
|
suite.txBuilder.SetGasLimit(gasLimit)
|
||||||
|
|
||||||
|
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
|
||||||
|
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
sud := ante.NewSetUpContextDecorator()
|
||||||
|
antehandler := sdk.ChainAnteDecorators(sud)
|
||||||
|
|
||||||
|
// Set height to non-zero value for GasMeter to be set
|
||||||
|
suite.ctx = suite.ctx.WithBlockHeight(1)
|
||||||
|
|
||||||
|
// Context GasMeter Limit not set
|
||||||
|
suite.Require().Equal(uint64(0), suite.ctx.GasMeter().Limit(), "GasMeter set with limit before setup")
|
||||||
|
|
||||||
|
newCtx, err := antehandler(suite.ctx, tx, false)
|
||||||
|
suite.Require().Nil(err, "SetUpContextDecorator returned error")
|
||||||
|
|
||||||
|
// Context GasMeter Limit should be set after SetUpContextDecorator runs
|
||||||
|
suite.Require().Equal(gasLimit, newCtx.GasMeter().Limit(), "GasMeter not set correctly")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) TestRecoverPanic() {
|
||||||
|
suite.SetupTest(true) // setup
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||||
|
|
||||||
|
// keys and addresses
|
||||||
|
priv1, _, addr1 := testdata.KeyTestPubAddr()
|
||||||
|
|
||||||
|
// msg and signatures
|
||||||
|
msg := testdata.NewTestMsg(addr1)
|
||||||
|
feeAmount := testdata.NewTestFeeAmount()
|
||||||
|
gasLimit := testdata.NewTestGasLimit()
|
||||||
|
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
|
||||||
|
suite.txBuilder.SetFeeAmount(feeAmount)
|
||||||
|
suite.txBuilder.SetGasLimit(gasLimit)
|
||||||
|
|
||||||
|
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
|
||||||
|
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
sud := ante.NewSetUpContextDecorator()
|
||||||
|
antehandler := sdk.ChainAnteDecorators(sud, OutOfGasDecorator{})
|
||||||
|
|
||||||
|
// Set height to non-zero value for GasMeter to be set
|
||||||
|
suite.ctx = suite.ctx.WithBlockHeight(1)
|
||||||
|
|
||||||
|
newCtx, err := antehandler(suite.ctx, tx, false)
|
||||||
|
|
||||||
|
suite.Require().NotNil(err, "Did not return error on OutOfGas panic")
|
||||||
|
|
||||||
|
suite.Require().True(sdkerrors.ErrOutOfGas.Is(err), "Returned error is not an out of gas error")
|
||||||
|
suite.Require().Equal(gasLimit, newCtx.GasMeter().Limit())
|
||||||
|
|
||||||
|
antehandler = sdk.ChainAnteDecorators(sud, PanicDecorator{})
|
||||||
|
suite.Require().Panics(func() { antehandler(suite.ctx, tx, false) }, "Recovered from non-Out-of-Gas panic") // nolint:errcheck
|
||||||
|
}
|
||||||
|
|
||||||
|
type OutOfGasDecorator struct{}
|
||||||
|
|
||||||
|
// AnteDecorator that will throw OutOfGas panic
|
||||||
|
func (ogd OutOfGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||||
|
overLimit := ctx.GasMeter().Limit() + 1
|
||||||
|
|
||||||
|
// Should panic with outofgas error
|
||||||
|
ctx.GasMeter().ConsumeGas(overLimit, "test panic")
|
||||||
|
|
||||||
|
// not reached
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
type PanicDecorator struct{}
|
||||||
|
|
||||||
|
func (pd PanicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||||
|
panic("random error")
|
||||||
|
}
|
510
x/auth/ante/sigverify.go
Normal file
510
x/auth/ante/sigverify.go
Normal file
@ -0,0 +1,510 @@
|
|||||||
|
package ante
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||||
|
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
|
||||||
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
|
||||||
|
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// simulation signature values used to estimate gas consumption
|
||||||
|
key = make([]byte, secp256k1.PubKeySize)
|
||||||
|
simSecp256k1Pubkey = &secp256k1.PubKey{Key: key}
|
||||||
|
simSecp256k1Sig [64]byte
|
||||||
|
|
||||||
|
_ authsigning.SigVerifiableTx = (*legacytx.StdTx)(nil) // assert StdTx implements SigVerifiableTx
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// This decodes a valid hex string into a sepc256k1Pubkey for use in transaction simulation
|
||||||
|
bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A")
|
||||||
|
copy(key, bz)
|
||||||
|
simSecp256k1Pubkey.Key = key
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignatureVerificationGasConsumer is the type of function that is used to both
|
||||||
|
// consume gas when verifying signatures and also to accept or reject different types of pubkeys
|
||||||
|
// This is where apps can define their own PubKey
|
||||||
|
type SignatureVerificationGasConsumer = func(meter sdk.GasMeter, sig signing.SignatureV2, params types.Params) error
|
||||||
|
|
||||||
|
// SetPubKeyDecorator sets PubKeys in context for any signer which does not already have pubkey set
|
||||||
|
// PubKeys must be set in context for all signers before any other sigverify decorators run
|
||||||
|
// CONTRACT: Tx must implement SigVerifiableTx interface
|
||||||
|
type SetPubKeyDecorator struct {
|
||||||
|
ak AccountKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSetPubKeyDecorator(ak AccountKeeper) SetPubKeyDecorator {
|
||||||
|
return SetPubKeyDecorator{
|
||||||
|
ak: ak,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (spkd SetPubKeyDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||||
|
sigTx, ok := tx.(authsigning.SigVerifiableTx)
|
||||||
|
if !ok {
|
||||||
|
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid tx type")
|
||||||
|
}
|
||||||
|
|
||||||
|
pubkeys, err := sigTx.GetPubKeys()
|
||||||
|
if err != nil {
|
||||||
|
return ctx, err
|
||||||
|
}
|
||||||
|
signers := sigTx.GetSigners()
|
||||||
|
|
||||||
|
for i, pk := range pubkeys {
|
||||||
|
// PublicKey was omitted from slice since it has already been set in context
|
||||||
|
if pk == nil {
|
||||||
|
if !simulate {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pk = simSecp256k1Pubkey
|
||||||
|
}
|
||||||
|
// Only make check if simulate=false
|
||||||
|
if !simulate && !bytes.Equal(pk.Address(), signers[i]) {
|
||||||
|
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey,
|
||||||
|
"pubKey does not match signer address %s with signer index: %d", signers[i], i)
|
||||||
|
}
|
||||||
|
|
||||||
|
acc, err := GetSignerAcc(ctx, spkd.ak, signers[i])
|
||||||
|
if err != nil {
|
||||||
|
return ctx, err
|
||||||
|
}
|
||||||
|
// account already has pubkey set,no need to reset
|
||||||
|
if acc.GetPubKey() != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err = acc.SetPubKey(pk)
|
||||||
|
if err != nil {
|
||||||
|
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, err.Error())
|
||||||
|
}
|
||||||
|
spkd.ak.SetAccount(ctx, acc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also emit the following events, so that txs can be indexed by these
|
||||||
|
// indices:
|
||||||
|
// - signature (via `tx.signature='<sig_as_base64>'`),
|
||||||
|
// - concat(address,"/",sequence) (via `tx.acc_seq='cosmos1abc...def/42'`).
|
||||||
|
sigs, err := sigTx.GetSignaturesV2()
|
||||||
|
if err != nil {
|
||||||
|
return ctx, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var events sdk.Events
|
||||||
|
for i, sig := range sigs {
|
||||||
|
events = append(events, sdk.NewEvent(sdk.EventTypeTx,
|
||||||
|
sdk.NewAttribute(sdk.AttributeKeyAccountSequence, fmt.Sprintf("%s/%d", signers[i], sig.Sequence)),
|
||||||
|
))
|
||||||
|
|
||||||
|
sigBzs, err := signatureDataToBz(sig.Data)
|
||||||
|
if err != nil {
|
||||||
|
return ctx, err
|
||||||
|
}
|
||||||
|
for _, sigBz := range sigBzs {
|
||||||
|
events = append(events, sdk.NewEvent(sdk.EventTypeTx,
|
||||||
|
sdk.NewAttribute(sdk.AttributeKeySignature, base64.StdEncoding.EncodeToString(sigBz)),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.EventManager().EmitEvents(events)
|
||||||
|
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consume parameter-defined amount of gas for each signature according to the passed-in SignatureVerificationGasConsumer function
|
||||||
|
// before calling the next AnteHandler
|
||||||
|
// CONTRACT: Pubkeys are set in context for all signers before this decorator runs
|
||||||
|
// CONTRACT: Tx must implement SigVerifiableTx interface
|
||||||
|
type SigGasConsumeDecorator struct {
|
||||||
|
ak AccountKeeper
|
||||||
|
sigGasConsumer SignatureVerificationGasConsumer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSigGasConsumeDecorator(ak AccountKeeper, sigGasConsumer SignatureVerificationGasConsumer) SigGasConsumeDecorator {
|
||||||
|
return SigGasConsumeDecorator{
|
||||||
|
ak: ak,
|
||||||
|
sigGasConsumer: sigGasConsumer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sgcd SigGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||||
|
sigTx, ok := tx.(authsigning.SigVerifiableTx)
|
||||||
|
if !ok {
|
||||||
|
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
|
||||||
|
}
|
||||||
|
|
||||||
|
params := sgcd.ak.GetParams(ctx)
|
||||||
|
sigs, err := sigTx.GetSignaturesV2()
|
||||||
|
if err != nil {
|
||||||
|
return ctx, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// stdSigs contains the sequence number, account number, and signatures.
|
||||||
|
// When simulating, this would just be a 0-length slice.
|
||||||
|
signerAddrs := sigTx.GetSigners()
|
||||||
|
|
||||||
|
for i, sig := range sigs {
|
||||||
|
signerAcc, err := GetSignerAcc(ctx, sgcd.ak, signerAddrs[i])
|
||||||
|
if err != nil {
|
||||||
|
return ctx, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pubKey := signerAcc.GetPubKey()
|
||||||
|
|
||||||
|
// In simulate mode the transaction comes with no signatures, thus if the
|
||||||
|
// account's pubkey is nil, both signature verification and gasKVStore.Set()
|
||||||
|
// shall consume the largest amount, i.e. it takes more gas to verify
|
||||||
|
// secp256k1 keys than ed25519 ones.
|
||||||
|
if simulate && pubKey == nil {
|
||||||
|
pubKey = simSecp256k1Pubkey
|
||||||
|
}
|
||||||
|
|
||||||
|
// make a SignatureV2 with PubKey filled in from above
|
||||||
|
sig = signing.SignatureV2{
|
||||||
|
PubKey: pubKey,
|
||||||
|
Data: sig.Data,
|
||||||
|
Sequence: sig.Sequence,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sgcd.sigGasConsumer(ctx.GasMeter(), sig, params)
|
||||||
|
if err != nil {
|
||||||
|
return ctx, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify all signatures for a tx and return an error if any are invalid. Note,
|
||||||
|
// the SigVerificationDecorator decorator will not get executed on ReCheck.
|
||||||
|
//
|
||||||
|
// CONTRACT: Pubkeys are set in context for all signers before this decorator runs
|
||||||
|
// CONTRACT: Tx must implement SigVerifiableTx interface
|
||||||
|
type SigVerificationDecorator struct {
|
||||||
|
ak AccountKeeper
|
||||||
|
signModeHandler authsigning.SignModeHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSigVerificationDecorator(ak AccountKeeper, signModeHandler authsigning.SignModeHandler) SigVerificationDecorator {
|
||||||
|
return SigVerificationDecorator{
|
||||||
|
ak: ak,
|
||||||
|
signModeHandler: signModeHandler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnlyLegacyAminoSigners checks SignatureData to see if all
|
||||||
|
// signers are using SIGN_MODE_LEGACY_AMINO_JSON. If this is the case
|
||||||
|
// then the corresponding SignatureV2 struct will not have account sequence
|
||||||
|
// explicitly set, and we should skip the explicit verification of sig.Sequence
|
||||||
|
// in the SigVerificationDecorator's AnteHandler function.
|
||||||
|
func OnlyLegacyAminoSigners(sigData signing.SignatureData) bool {
|
||||||
|
switch v := sigData.(type) {
|
||||||
|
case *signing.SingleSignatureData:
|
||||||
|
return v.SignMode == signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON
|
||||||
|
case *signing.MultiSignatureData:
|
||||||
|
for _, s := range v.Signatures {
|
||||||
|
if !OnlyLegacyAminoSigners(s) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (svd SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||||
|
// no need to verify signatures on recheck tx
|
||||||
|
if ctx.IsReCheckTx() {
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
||||||
|
sigTx, ok := tx.(authsigning.SigVerifiableTx)
|
||||||
|
if !ok {
|
||||||
|
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
|
||||||
|
}
|
||||||
|
|
||||||
|
// stdSigs contains the sequence number, account number, and signatures.
|
||||||
|
// When simulating, this would just be a 0-length slice.
|
||||||
|
sigs, err := sigTx.GetSignaturesV2()
|
||||||
|
if err != nil {
|
||||||
|
return ctx, err
|
||||||
|
}
|
||||||
|
|
||||||
|
signerAddrs := sigTx.GetSigners()
|
||||||
|
|
||||||
|
// check that signer length and signature length are the same
|
||||||
|
if len(sigs) != len(signerAddrs) {
|
||||||
|
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signerAddrs), len(sigs))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, sig := range sigs {
|
||||||
|
acc, err := GetSignerAcc(ctx, svd.ak, signerAddrs[i])
|
||||||
|
if err != nil {
|
||||||
|
return ctx, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// retrieve pubkey
|
||||||
|
pubKey := acc.GetPubKey()
|
||||||
|
if !simulate && pubKey == nil {
|
||||||
|
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "pubkey on account is not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check account sequence number.
|
||||||
|
if sig.Sequence != acc.GetSequence() {
|
||||||
|
return ctx, sdkerrors.Wrapf(
|
||||||
|
sdkerrors.ErrWrongSequence,
|
||||||
|
"account sequence mismatch, expected %d, got %d", acc.GetSequence(), sig.Sequence,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// retrieve signer data
|
||||||
|
genesis := ctx.BlockHeight() == 0
|
||||||
|
chainID := ctx.ChainID()
|
||||||
|
var accNum uint64
|
||||||
|
if !genesis {
|
||||||
|
accNum = acc.GetAccountNumber()
|
||||||
|
}
|
||||||
|
signerData := authsigning.SignerData{
|
||||||
|
ChainID: chainID,
|
||||||
|
AccountNumber: accNum,
|
||||||
|
Sequence: acc.GetSequence(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if !simulate {
|
||||||
|
err := authsigning.VerifySignature(pubKey, signerData, sig.Data, svd.signModeHandler, tx)
|
||||||
|
if err != nil {
|
||||||
|
var errMsg string
|
||||||
|
if OnlyLegacyAminoSigners(sig.Data) {
|
||||||
|
// If all signers are using SIGN_MODE_LEGACY_AMINO, we rely on VerifySignature to check account sequence number,
|
||||||
|
// and therefore communicate sequence number as a potential cause of error.
|
||||||
|
errMsg = fmt.Sprintf("signature verification failed; please verify account number (%d), sequence (%d) and chain-id (%s)", accNum, acc.GetSequence(), chainID)
|
||||||
|
} else {
|
||||||
|
errMsg = fmt.Sprintf("signature verification failed; please verify account number (%d) and chain-id (%s)", accNum, chainID)
|
||||||
|
}
|
||||||
|
return ctx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, errMsg)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncrementSequenceDecorator handles incrementing sequences of all signers.
|
||||||
|
// Use the IncrementSequenceDecorator decorator to prevent replay attacks. Note,
|
||||||
|
// there is no need to execute IncrementSequenceDecorator on RecheckTX since
|
||||||
|
// CheckTx would already bump the sequence number.
|
||||||
|
//
|
||||||
|
// NOTE: Since CheckTx and DeliverTx state are managed separately, subsequent and
|
||||||
|
// sequential txs orginating from the same account cannot be handled correctly in
|
||||||
|
// a reliable way unless sequence numbers are managed and tracked manually by a
|
||||||
|
// client. It is recommended to instead use multiple messages in a tx.
|
||||||
|
type IncrementSequenceDecorator struct {
|
||||||
|
ak AccountKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewIncrementSequenceDecorator(ak AccountKeeper) IncrementSequenceDecorator {
|
||||||
|
return IncrementSequenceDecorator{
|
||||||
|
ak: ak,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (isd IncrementSequenceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||||
|
sigTx, ok := tx.(authsigning.SigVerifiableTx)
|
||||||
|
if !ok {
|
||||||
|
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
|
||||||
|
}
|
||||||
|
|
||||||
|
// increment sequence of all signers
|
||||||
|
for _, addr := range sigTx.GetSigners() {
|
||||||
|
acc := isd.ak.GetAccount(ctx, addr)
|
||||||
|
if err := acc.SetSequence(acc.GetSequence() + 1); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
isd.ak.SetAccount(ctx, acc)
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateSigCountDecorator takes in Params and returns errors if there are too many signatures in the tx for the given params
|
||||||
|
// otherwise it calls next AnteHandler
|
||||||
|
// Use this decorator to set parameterized limit on number of signatures in tx
|
||||||
|
// CONTRACT: Tx must implement SigVerifiableTx interface
|
||||||
|
type ValidateSigCountDecorator struct {
|
||||||
|
ak AccountKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewValidateSigCountDecorator(ak AccountKeeper) ValidateSigCountDecorator {
|
||||||
|
return ValidateSigCountDecorator{
|
||||||
|
ak: ak,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vscd ValidateSigCountDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||||
|
sigTx, ok := tx.(authsigning.SigVerifiableTx)
|
||||||
|
if !ok {
|
||||||
|
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a sigTx")
|
||||||
|
}
|
||||||
|
|
||||||
|
params := vscd.ak.GetParams(ctx)
|
||||||
|
pubKeys, err := sigTx.GetPubKeys()
|
||||||
|
if err != nil {
|
||||||
|
return ctx, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sigCount := 0
|
||||||
|
for _, pk := range pubKeys {
|
||||||
|
sigCount += CountSubKeys(pk)
|
||||||
|
if uint64(sigCount) > params.TxSigLimit {
|
||||||
|
return ctx, sdkerrors.Wrapf(sdkerrors.ErrTooManySignatures,
|
||||||
|
"signatures: %d, limit: %d", sigCount, params.TxSigLimit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(ctx, tx, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas
|
||||||
|
// for signature verification based upon the public key type. The cost is fetched from the given params and is matched
|
||||||
|
// by the concrete type.
|
||||||
|
func DefaultSigVerificationGasConsumer(
|
||||||
|
meter sdk.GasMeter, sig signing.SignatureV2, params types.Params,
|
||||||
|
) error {
|
||||||
|
pubkey := sig.PubKey
|
||||||
|
switch pubkey := pubkey.(type) {
|
||||||
|
case *ed25519.PubKey:
|
||||||
|
meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519")
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "ED25519 public keys are unsupported")
|
||||||
|
|
||||||
|
case *secp256k1.PubKey:
|
||||||
|
meter.ConsumeGas(params.SigVerifyCostSecp256k1, "ante verify: secp256k1")
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case *secp256r1.PubKey:
|
||||||
|
meter.ConsumeGas(params.SigVerifyCostSecp256r1(), "ante verify: secp256r1")
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case multisig.PubKey:
|
||||||
|
multisignature, ok := sig.Data.(*signing.MultiSignatureData)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("expected %T, got, %T", &signing.MultiSignatureData{}, sig.Data)
|
||||||
|
}
|
||||||
|
err := ConsumeMultisignatureVerificationGas(meter, multisignature, pubkey, params, sig.Sequence)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "unrecognized public key type: %T", pubkey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConsumeMultisignatureVerificationGas consumes gas from a GasMeter for verifying a multisig pubkey signature
|
||||||
|
func ConsumeMultisignatureVerificationGas(
|
||||||
|
meter sdk.GasMeter, sig *signing.MultiSignatureData, pubkey multisig.PubKey,
|
||||||
|
params types.Params, accSeq uint64,
|
||||||
|
) error {
|
||||||
|
|
||||||
|
size := sig.BitArray.Count()
|
||||||
|
sigIndex := 0
|
||||||
|
|
||||||
|
for i := 0; i < size; i++ {
|
||||||
|
if !sig.BitArray.GetIndex(i) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sigV2 := signing.SignatureV2{
|
||||||
|
PubKey: pubkey.GetPubKeys()[i],
|
||||||
|
Data: sig.Signatures[sigIndex],
|
||||||
|
Sequence: accSeq,
|
||||||
|
}
|
||||||
|
err := DefaultSigVerificationGasConsumer(meter, sigV2, params)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sigIndex++
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSignerAcc returns an account for a given address that is expected to sign
|
||||||
|
// a transaction.
|
||||||
|
func GetSignerAcc(ctx sdk.Context, ak AccountKeeper, addr sdk.AccAddress) (types.AccountI, error) {
|
||||||
|
if acc := ak.GetAccount(ctx, addr); acc != nil {
|
||||||
|
return acc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountSubKeys counts the total number of keys for a multi-sig public key.
|
||||||
|
func CountSubKeys(pub cryptotypes.PubKey) int {
|
||||||
|
v, ok := pub.(*kmultisig.LegacyAminoPubKey)
|
||||||
|
if !ok {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
numKeys := 0
|
||||||
|
for _, subkey := range v.GetPubKeys() {
|
||||||
|
numKeys += CountSubKeys(subkey)
|
||||||
|
}
|
||||||
|
|
||||||
|
return numKeys
|
||||||
|
}
|
||||||
|
|
||||||
|
// signatureDataToBz converts a SignatureData into raw bytes signature.
|
||||||
|
// For SingleSignatureData, it returns the signature raw bytes.
|
||||||
|
// For MultiSignatureData, it returns an array of all individual signatures,
|
||||||
|
// as well as the aggregated signature.
|
||||||
|
func signatureDataToBz(data signing.SignatureData) ([][]byte, error) {
|
||||||
|
if data == nil {
|
||||||
|
return nil, fmt.Errorf("got empty SignatureData")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch data := data.(type) {
|
||||||
|
case *signing.SingleSignatureData:
|
||||||
|
return [][]byte{data.Signature}, nil
|
||||||
|
case *signing.MultiSignatureData:
|
||||||
|
sigs := [][]byte{}
|
||||||
|
var err error
|
||||||
|
|
||||||
|
for _, d := range data.Signatures {
|
||||||
|
nestedSigs, err := signatureDataToBz(d)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sigs = append(sigs, nestedSigs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
multisig := cryptotypes.MultiSignature{
|
||||||
|
Signatures: sigs,
|
||||||
|
}
|
||||||
|
aggregatedSig, err := multisig.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sigs = append(sigs, aggregatedSig)
|
||||||
|
|
||||||
|
return sigs, nil
|
||||||
|
default:
|
||||||
|
return nil, sdkerrors.ErrInvalidType.Wrapf("unexpected signature data type %T", data)
|
||||||
|
}
|
||||||
|
}
|
44
x/auth/ante/sigverify_benchmark_test.go
Normal file
44
x/auth/ante/sigverify_benchmark_test.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package ante_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
tmcrypto "github.com/tendermint/tendermint/crypto"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This benchmark is used to asses the ante.Secp256k1ToR1GasFactor value
|
||||||
|
func BenchmarkSig(b *testing.B) {
|
||||||
|
require := require.New(b)
|
||||||
|
msg := tmcrypto.CRandBytes(1000)
|
||||||
|
|
||||||
|
skK := secp256k1.GenPrivKey()
|
||||||
|
pkK := skK.PubKey()
|
||||||
|
skR, _ := secp256r1.GenPrivKey()
|
||||||
|
pkR := skR.PubKey()
|
||||||
|
|
||||||
|
sigK, err := skK.Sign(msg)
|
||||||
|
require.NoError(err)
|
||||||
|
sigR, err := skR.Sign(msg)
|
||||||
|
require.NoError(err)
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
b.Run("secp256k1", func(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
ok := pkK.VerifySignature(msg, sigK)
|
||||||
|
require.True(ok)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("secp256r1", func(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
ok := pkR.VerifySignature(msg, sigR)
|
||||||
|
require.True(ok)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
390
x/auth/ante/sigverify_test.go
Normal file
390
x/auth/ante/sigverify_test.go
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
package ante_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||||
|
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
|
||||||
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||||
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) TestSetPubKey() {
|
||||||
|
suite.SetupTest(true) // setup
|
||||||
|
require := suite.Require()
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||||
|
|
||||||
|
// keys and addresses
|
||||||
|
priv1, pub1, addr1 := testdata.KeyTestPubAddr()
|
||||||
|
priv2, pub2, addr2 := testdata.KeyTestPubAddr()
|
||||||
|
priv3, pub3, addr3 := testdata.KeyTestPubAddrSecp256R1(require)
|
||||||
|
|
||||||
|
addrs := []sdk.AccAddress{addr1, addr2, addr3}
|
||||||
|
pubs := []cryptotypes.PubKey{pub1, pub2, pub3}
|
||||||
|
|
||||||
|
msgs := make([]sdk.Msg, len(addrs))
|
||||||
|
// set accounts and create msg for each address
|
||||||
|
for i, addr := range addrs {
|
||||||
|
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr)
|
||||||
|
require.NoError(acc.SetAccountNumber(uint64(i)))
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||||
|
msgs[i] = testdata.NewTestMsg(addr)
|
||||||
|
}
|
||||||
|
require.NoError(suite.txBuilder.SetMsgs(msgs...))
|
||||||
|
suite.txBuilder.SetFeeAmount(testdata.NewTestFeeAmount())
|
||||||
|
suite.txBuilder.SetGasLimit(testdata.NewTestGasLimit())
|
||||||
|
|
||||||
|
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0}
|
||||||
|
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
|
||||||
|
require.NoError(err)
|
||||||
|
|
||||||
|
spkd := ante.NewSetPubKeyDecorator(suite.app.AccountKeeper)
|
||||||
|
antehandler := sdk.ChainAnteDecorators(spkd)
|
||||||
|
|
||||||
|
ctx, err := antehandler(suite.ctx, tx, false)
|
||||||
|
require.NoError(err)
|
||||||
|
|
||||||
|
// Require that all accounts have pubkey set after Decorator runs
|
||||||
|
for i, addr := range addrs {
|
||||||
|
pk, err := suite.app.AccountKeeper.GetPubKey(ctx, addr)
|
||||||
|
require.NoError(err, "Error on retrieving pubkey from account")
|
||||||
|
require.True(pubs[i].Equals(pk),
|
||||||
|
"Wrong Pubkey retrieved from AccountKeeper, idx=%d\nexpected=%s\n got=%s", i, pubs[i], pk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) TestConsumeSignatureVerificationGas() {
|
||||||
|
params := types.DefaultParams()
|
||||||
|
msg := []byte{1, 2, 3, 4}
|
||||||
|
cdc := simapp.MakeTestEncodingConfig().Amino
|
||||||
|
|
||||||
|
p := types.DefaultParams()
|
||||||
|
skR1, _ := secp256r1.GenPrivKey()
|
||||||
|
pkSet1, sigSet1 := generatePubKeysAndSignatures(5, msg, false)
|
||||||
|
multisigKey1 := kmultisig.NewLegacyAminoPubKey(2, pkSet1)
|
||||||
|
multisignature1 := multisig.NewMultisig(len(pkSet1))
|
||||||
|
expectedCost1 := expectedGasCostByKeys(pkSet1)
|
||||||
|
for i := 0; i < len(pkSet1); i++ {
|
||||||
|
stdSig := legacytx.StdSignature{PubKey: pkSet1[i], Signature: sigSet1[i]}
|
||||||
|
sigV2, err := legacytx.StdSignatureToSignatureV2(cdc, stdSig)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
err = multisig.AddSignatureV2(multisignature1, sigV2, pkSet1)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
meter sdk.GasMeter
|
||||||
|
sig signing.SignatureData
|
||||||
|
pubkey cryptotypes.PubKey
|
||||||
|
params types.Params
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
gasConsumed uint64
|
||||||
|
shouldErr bool
|
||||||
|
}{
|
||||||
|
{"PubKeyEd25519", args{sdk.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, p.SigVerifyCostED25519, true},
|
||||||
|
{"PubKeySecp256k1", args{sdk.NewInfiniteGasMeter(), nil, secp256k1.GenPrivKey().PubKey(), params}, p.SigVerifyCostSecp256k1, false},
|
||||||
|
{"PubKeySecp256r1", args{sdk.NewInfiniteGasMeter(), nil, skR1.PubKey(), params}, p.SigVerifyCostSecp256r1(), false},
|
||||||
|
{"Multisig", args{sdk.NewInfiniteGasMeter(), multisignature1, multisigKey1, params}, expectedCost1, false},
|
||||||
|
{"unknown key", args{sdk.NewInfiniteGasMeter(), nil, nil, params}, 0, true},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
sigV2 := signing.SignatureV2{
|
||||||
|
PubKey: tt.args.pubkey,
|
||||||
|
Data: tt.args.sig,
|
||||||
|
Sequence: 0, // Arbitrary account sequence
|
||||||
|
}
|
||||||
|
err := ante.DefaultSigVerificationGasConsumer(tt.args.meter, sigV2, tt.args.params)
|
||||||
|
|
||||||
|
if tt.shouldErr {
|
||||||
|
suite.Require().NotNil(err)
|
||||||
|
} else {
|
||||||
|
suite.Require().Nil(err)
|
||||||
|
suite.Require().Equal(tt.gasConsumed, tt.args.meter.GasConsumed(), fmt.Sprintf("%d != %d", tt.gasConsumed, tt.args.meter.GasConsumed()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) TestSigVerification() {
|
||||||
|
suite.SetupTest(true) // setup
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||||
|
|
||||||
|
// make block height non-zero to ensure account numbers part of signBytes
|
||||||
|
suite.ctx = suite.ctx.WithBlockHeight(1)
|
||||||
|
|
||||||
|
// keys and addresses
|
||||||
|
priv1, _, addr1 := testdata.KeyTestPubAddr()
|
||||||
|
priv2, _, addr2 := testdata.KeyTestPubAddr()
|
||||||
|
priv3, _, addr3 := testdata.KeyTestPubAddr()
|
||||||
|
|
||||||
|
addrs := []sdk.AccAddress{addr1, addr2, addr3}
|
||||||
|
|
||||||
|
msgs := make([]sdk.Msg, len(addrs))
|
||||||
|
// set accounts and create msg for each address
|
||||||
|
for i, addr := range addrs {
|
||||||
|
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr)
|
||||||
|
suite.Require().NoError(acc.SetAccountNumber(uint64(i)))
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||||
|
msgs[i] = testdata.NewTestMsg(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
feeAmount := testdata.NewTestFeeAmount()
|
||||||
|
gasLimit := testdata.NewTestGasLimit()
|
||||||
|
|
||||||
|
spkd := ante.NewSetPubKeyDecorator(suite.app.AccountKeeper)
|
||||||
|
svd := ante.NewSigVerificationDecorator(suite.app.AccountKeeper, suite.clientCtx.TxConfig.SignModeHandler())
|
||||||
|
antehandler := sdk.ChainAnteDecorators(spkd, svd)
|
||||||
|
|
||||||
|
type testCase struct {
|
||||||
|
name string
|
||||||
|
privs []cryptotypes.PrivKey
|
||||||
|
accNums []uint64
|
||||||
|
accSeqs []uint64
|
||||||
|
recheck bool
|
||||||
|
shouldErr bool
|
||||||
|
}
|
||||||
|
testCases := []testCase{
|
||||||
|
{"no signers", []cryptotypes.PrivKey{}, []uint64{}, []uint64{}, false, true},
|
||||||
|
{"not enough signers", []cryptotypes.PrivKey{priv1, priv2}, []uint64{0, 1}, []uint64{0, 0}, false, true},
|
||||||
|
{"wrong order signers", []cryptotypes.PrivKey{priv3, priv2, priv1}, []uint64{2, 1, 0}, []uint64{0, 0, 0}, false, true},
|
||||||
|
{"wrong accnums", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{7, 8, 9}, []uint64{0, 0, 0}, false, true},
|
||||||
|
{"wrong sequences", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{3, 4, 5}, false, true},
|
||||||
|
{"valid tx", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0}, false, false},
|
||||||
|
{"no err on recheck", []cryptotypes.PrivKey{}, []uint64{}, []uint64{}, true, false},
|
||||||
|
}
|
||||||
|
for i, tc := range testCases {
|
||||||
|
suite.ctx = suite.ctx.WithIsReCheckTx(tc.recheck)
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() // Create new txBuilder for each test
|
||||||
|
|
||||||
|
suite.Require().NoError(suite.txBuilder.SetMsgs(msgs...))
|
||||||
|
suite.txBuilder.SetFeeAmount(feeAmount)
|
||||||
|
suite.txBuilder.SetGasLimit(gasLimit)
|
||||||
|
|
||||||
|
tx, err := suite.CreateTestTx(tc.privs, tc.accNums, tc.accSeqs, suite.ctx.ChainID())
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
_, err = antehandler(suite.ctx, tx, false)
|
||||||
|
if tc.shouldErr {
|
||||||
|
suite.Require().NotNil(err, "TestCase %d: %s did not error as expected", i, tc.name)
|
||||||
|
} else {
|
||||||
|
suite.Require().Nil(err, "TestCase %d: %s errored unexpectedly. Err: %v", i, tc.name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test is exactly like the one above, but we set the codec explicitly to
|
||||||
|
// Amino.
|
||||||
|
// Once https://github.com/cosmos/cosmos-sdk/issues/6190 is in, we can remove
|
||||||
|
// this, since it'll be handled by the test matrix.
|
||||||
|
// In the meantime, we want to make double-sure amino compatibility works.
|
||||||
|
// ref: https://github.com/cosmos/cosmos-sdk/issues/7229
|
||||||
|
func (suite *AnteTestSuite) TestSigVerification_ExplicitAmino() {
|
||||||
|
suite.app, suite.ctx = createTestApp(true)
|
||||||
|
suite.ctx = suite.ctx.WithBlockHeight(1)
|
||||||
|
|
||||||
|
// Set up TxConfig.
|
||||||
|
aminoCdc := codec.NewLegacyAmino()
|
||||||
|
// We're using TestMsg amino encoding in some tests, so register it here.
|
||||||
|
txConfig := legacytx.StdTxConfig{Cdc: aminoCdc}
|
||||||
|
|
||||||
|
suite.clientCtx = client.Context{}.
|
||||||
|
WithTxConfig(txConfig)
|
||||||
|
|
||||||
|
anteHandler, err := ante.NewAnteHandler(
|
||||||
|
ante.HandlerOptions{
|
||||||
|
AccountKeeper: suite.app.AccountKeeper,
|
||||||
|
BankKeeper: suite.app.BankKeeper,
|
||||||
|
FeegrantKeeper: suite.app.FeeGrantKeeper,
|
||||||
|
SignModeHandler: txConfig.SignModeHandler(),
|
||||||
|
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.anteHandler = anteHandler
|
||||||
|
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||||
|
|
||||||
|
// make block height non-zero to ensure account numbers part of signBytes
|
||||||
|
suite.ctx = suite.ctx.WithBlockHeight(1)
|
||||||
|
|
||||||
|
// keys and addresses
|
||||||
|
priv1, _, addr1 := testdata.KeyTestPubAddr()
|
||||||
|
priv2, _, addr2 := testdata.KeyTestPubAddr()
|
||||||
|
priv3, _, addr3 := testdata.KeyTestPubAddr()
|
||||||
|
|
||||||
|
addrs := []sdk.AccAddress{addr1, addr2, addr3}
|
||||||
|
|
||||||
|
msgs := make([]sdk.Msg, len(addrs))
|
||||||
|
// set accounts and create msg for each address
|
||||||
|
for i, addr := range addrs {
|
||||||
|
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr)
|
||||||
|
suite.Require().NoError(acc.SetAccountNumber(uint64(i)))
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||||
|
msgs[i] = testdata.NewTestMsg(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
feeAmount := testdata.NewTestFeeAmount()
|
||||||
|
gasLimit := testdata.NewTestGasLimit()
|
||||||
|
|
||||||
|
spkd := ante.NewSetPubKeyDecorator(suite.app.AccountKeeper)
|
||||||
|
svd := ante.NewSigVerificationDecorator(suite.app.AccountKeeper, suite.clientCtx.TxConfig.SignModeHandler())
|
||||||
|
antehandler := sdk.ChainAnteDecorators(spkd, svd)
|
||||||
|
|
||||||
|
type testCase struct {
|
||||||
|
name string
|
||||||
|
privs []cryptotypes.PrivKey
|
||||||
|
accNums []uint64
|
||||||
|
accSeqs []uint64
|
||||||
|
recheck bool
|
||||||
|
shouldErr bool
|
||||||
|
}
|
||||||
|
testCases := []testCase{
|
||||||
|
{"no signers", []cryptotypes.PrivKey{}, []uint64{}, []uint64{}, false, true},
|
||||||
|
{"not enough signers", []cryptotypes.PrivKey{priv1, priv2}, []uint64{0, 1}, []uint64{0, 0}, false, true},
|
||||||
|
{"wrong order signers", []cryptotypes.PrivKey{priv3, priv2, priv1}, []uint64{2, 1, 0}, []uint64{0, 0, 0}, false, true},
|
||||||
|
{"wrong accnums", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{7, 8, 9}, []uint64{0, 0, 0}, false, true},
|
||||||
|
{"wrong sequences", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{3, 4, 5}, false, true},
|
||||||
|
{"valid tx", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0}, false, false},
|
||||||
|
{"no err on recheck", []cryptotypes.PrivKey{}, []uint64{}, []uint64{}, true, false},
|
||||||
|
}
|
||||||
|
for i, tc := range testCases {
|
||||||
|
suite.ctx = suite.ctx.WithIsReCheckTx(tc.recheck)
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() // Create new txBuilder for each test
|
||||||
|
|
||||||
|
suite.Require().NoError(suite.txBuilder.SetMsgs(msgs...))
|
||||||
|
suite.txBuilder.SetFeeAmount(feeAmount)
|
||||||
|
suite.txBuilder.SetGasLimit(gasLimit)
|
||||||
|
|
||||||
|
tx, err := suite.CreateTestTx(tc.privs, tc.accNums, tc.accSeqs, suite.ctx.ChainID())
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
_, err = antehandler(suite.ctx, tx, false)
|
||||||
|
if tc.shouldErr {
|
||||||
|
suite.Require().NotNil(err, "TestCase %d: %s did not error as expected", i, tc.name)
|
||||||
|
} else {
|
||||||
|
suite.Require().Nil(err, "TestCase %d: %s errored unexpectedly. Err: %v", i, tc.name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) TestSigIntegration() {
|
||||||
|
// generate private keys
|
||||||
|
privs := []cryptotypes.PrivKey{
|
||||||
|
secp256k1.GenPrivKey(),
|
||||||
|
secp256k1.GenPrivKey(),
|
||||||
|
secp256k1.GenPrivKey(),
|
||||||
|
}
|
||||||
|
|
||||||
|
params := types.DefaultParams()
|
||||||
|
initialSigCost := params.SigVerifyCostSecp256k1
|
||||||
|
initialCost, err := suite.runSigDecorators(params, false, privs...)
|
||||||
|
suite.Require().Nil(err)
|
||||||
|
|
||||||
|
params.SigVerifyCostSecp256k1 *= 2
|
||||||
|
doubleCost, err := suite.runSigDecorators(params, false, privs...)
|
||||||
|
suite.Require().Nil(err)
|
||||||
|
|
||||||
|
suite.Require().Equal(initialSigCost*uint64(len(privs)), doubleCost-initialCost)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) runSigDecorators(params types.Params, _ bool, privs ...cryptotypes.PrivKey) (sdk.Gas, error) {
|
||||||
|
suite.SetupTest(true) // setup
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||||
|
|
||||||
|
// Make block-height non-zero to include accNum in SignBytes
|
||||||
|
suite.ctx = suite.ctx.WithBlockHeight(1)
|
||||||
|
suite.app.AccountKeeper.SetParams(suite.ctx, params)
|
||||||
|
|
||||||
|
msgs := make([]sdk.Msg, len(privs))
|
||||||
|
accNums := make([]uint64, len(privs))
|
||||||
|
accSeqs := make([]uint64, len(privs))
|
||||||
|
// set accounts and create msg for each address
|
||||||
|
for i, priv := range privs {
|
||||||
|
addr := sdk.AccAddress(priv.PubKey().Address())
|
||||||
|
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr)
|
||||||
|
suite.Require().NoError(acc.SetAccountNumber(uint64(i)))
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||||
|
msgs[i] = testdata.NewTestMsg(addr)
|
||||||
|
accNums[i] = uint64(i)
|
||||||
|
accSeqs[i] = uint64(0)
|
||||||
|
}
|
||||||
|
suite.Require().NoError(suite.txBuilder.SetMsgs(msgs...))
|
||||||
|
|
||||||
|
feeAmount := testdata.NewTestFeeAmount()
|
||||||
|
gasLimit := testdata.NewTestGasLimit()
|
||||||
|
suite.txBuilder.SetFeeAmount(feeAmount)
|
||||||
|
suite.txBuilder.SetGasLimit(gasLimit)
|
||||||
|
|
||||||
|
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
spkd := ante.NewSetPubKeyDecorator(suite.app.AccountKeeper)
|
||||||
|
svgc := ante.NewSigGasConsumeDecorator(suite.app.AccountKeeper, ante.DefaultSigVerificationGasConsumer)
|
||||||
|
svd := ante.NewSigVerificationDecorator(suite.app.AccountKeeper, suite.clientCtx.TxConfig.SignModeHandler())
|
||||||
|
antehandler := sdk.ChainAnteDecorators(spkd, svgc, svd)
|
||||||
|
|
||||||
|
// Determine gas consumption of antehandler with default params
|
||||||
|
before := suite.ctx.GasMeter().GasConsumed()
|
||||||
|
ctx, err := antehandler(suite.ctx, tx, false)
|
||||||
|
after := ctx.GasMeter().GasConsumed()
|
||||||
|
|
||||||
|
return after - before, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) TestIncrementSequenceDecorator() {
|
||||||
|
suite.SetupTest(true) // setup
|
||||||
|
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||||
|
|
||||||
|
priv, _, addr := testdata.KeyTestPubAddr()
|
||||||
|
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr)
|
||||||
|
suite.Require().NoError(acc.SetAccountNumber(uint64(50)))
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||||
|
|
||||||
|
msgs := []sdk.Msg{testdata.NewTestMsg(addr)}
|
||||||
|
suite.Require().NoError(suite.txBuilder.SetMsgs(msgs...))
|
||||||
|
privs := []cryptotypes.PrivKey{priv}
|
||||||
|
accNums := []uint64{suite.app.AccountKeeper.GetAccount(suite.ctx, addr).GetAccountNumber()}
|
||||||
|
accSeqs := []uint64{suite.app.AccountKeeper.GetAccount(suite.ctx, addr).GetSequence()}
|
||||||
|
feeAmount := testdata.NewTestFeeAmount()
|
||||||
|
gasLimit := testdata.NewTestGasLimit()
|
||||||
|
suite.txBuilder.SetFeeAmount(feeAmount)
|
||||||
|
suite.txBuilder.SetGasLimit(gasLimit)
|
||||||
|
|
||||||
|
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
isd := ante.NewIncrementSequenceDecorator(suite.app.AccountKeeper)
|
||||||
|
antehandler := sdk.ChainAnteDecorators(isd)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
ctx sdk.Context
|
||||||
|
simulate bool
|
||||||
|
expectedSeq uint64
|
||||||
|
}{
|
||||||
|
{suite.ctx.WithIsReCheckTx(true), false, 1},
|
||||||
|
{suite.ctx.WithIsCheckTx(true).WithIsReCheckTx(false), false, 2},
|
||||||
|
{suite.ctx.WithIsReCheckTx(true), false, 3},
|
||||||
|
{suite.ctx.WithIsReCheckTx(true), false, 4},
|
||||||
|
{suite.ctx.WithIsReCheckTx(true), true, 5},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tc := range testCases {
|
||||||
|
_, err := antehandler(tc.ctx, tx, tc.simulate)
|
||||||
|
suite.Require().NoError(err, "unexpected error; tc #%d, %v", i, tc)
|
||||||
|
suite.Require().Equal(tc.expectedSeq, suite.app.AccountKeeper.GetAccount(suite.ctx, addr).GetSequence())
|
||||||
|
}
|
||||||
|
}
|
200
x/auth/ante/testutil_test.go
Normal file
200
x/auth/ante/testutil_test.go
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
package ante_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||||
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||||
|
xauthsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestAccount represents an account used in the tests in x/auth/ante.
|
||||||
|
type TestAccount struct {
|
||||||
|
acc types.AccountI
|
||||||
|
priv cryptotypes.PrivKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnteTestSuite is a test suite to be used with ante handler tests.
|
||||||
|
type AnteTestSuite struct {
|
||||||
|
suite.Suite
|
||||||
|
|
||||||
|
app *simapp.SimApp
|
||||||
|
anteHandler sdk.AnteHandler
|
||||||
|
ctx sdk.Context
|
||||||
|
clientCtx client.Context
|
||||||
|
txBuilder client.TxBuilder
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns context and app with params set on account keeper
|
||||||
|
func createTestApp(isCheckTx bool) (*simapp.SimApp, sdk.Context) {
|
||||||
|
app := simapp.Setup(isCheckTx)
|
||||||
|
ctx := app.BaseApp.NewContext(isCheckTx, tmproto.Header{})
|
||||||
|
app.AccountKeeper.SetParams(ctx, authtypes.DefaultParams())
|
||||||
|
|
||||||
|
return app, ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetupTest setups a new test, with new app, context, and anteHandler.
|
||||||
|
func (suite *AnteTestSuite) SetupTest(isCheckTx bool) {
|
||||||
|
suite.app, suite.ctx = createTestApp(isCheckTx)
|
||||||
|
suite.ctx = suite.ctx.WithBlockHeight(1)
|
||||||
|
|
||||||
|
// Set up TxConfig.
|
||||||
|
encodingConfig := simapp.MakeTestEncodingConfig()
|
||||||
|
// We're using TestMsg encoding in some tests, so register it here.
|
||||||
|
encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
|
||||||
|
testdata.RegisterInterfaces(encodingConfig.InterfaceRegistry)
|
||||||
|
|
||||||
|
suite.clientCtx = client.Context{}.
|
||||||
|
WithTxConfig(encodingConfig.TxConfig)
|
||||||
|
|
||||||
|
anteHandler, err := ante.NewAnteHandler(
|
||||||
|
ante.HandlerOptions{
|
||||||
|
AccountKeeper: suite.app.AccountKeeper,
|
||||||
|
BankKeeper: suite.app.BankKeeper,
|
||||||
|
FeegrantKeeper: suite.app.FeeGrantKeeper,
|
||||||
|
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
|
||||||
|
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.anteHandler = anteHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateTestAccounts creates `numAccs` accounts, and return all relevant
|
||||||
|
// information about them including their private keys.
|
||||||
|
func (suite *AnteTestSuite) CreateTestAccounts(numAccs int) []TestAccount {
|
||||||
|
var accounts []TestAccount
|
||||||
|
|
||||||
|
for i := 0; i < numAccs; i++ {
|
||||||
|
priv, _, addr := testdata.KeyTestPubAddr()
|
||||||
|
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr)
|
||||||
|
err := acc.SetAccountNumber(uint64(i))
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||||
|
someCoins := sdk.Coins{
|
||||||
|
sdk.NewInt64Coin("atom", 10000000),
|
||||||
|
}
|
||||||
|
err = suite.app.BankKeeper.MintCoins(suite.ctx, minttypes.ModuleName, someCoins)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, minttypes.ModuleName, addr, someCoins)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
accounts = append(accounts, TestAccount{acc, priv})
|
||||||
|
}
|
||||||
|
|
||||||
|
return accounts
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateTestTx is a helper function to create a tx given multiple inputs.
|
||||||
|
func (suite *AnteTestSuite) CreateTestTx(privs []cryptotypes.PrivKey, accNums []uint64, accSeqs []uint64, chainID string) (xauthsigning.Tx, error) {
|
||||||
|
// First round: we gather all the signer infos. We use the "set empty
|
||||||
|
// signature" hack to do that.
|
||||||
|
var sigsV2 []signing.SignatureV2
|
||||||
|
for i, priv := range privs {
|
||||||
|
sigV2 := signing.SignatureV2{
|
||||||
|
PubKey: priv.PubKey(),
|
||||||
|
Data: &signing.SingleSignatureData{
|
||||||
|
SignMode: suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(),
|
||||||
|
Signature: nil,
|
||||||
|
},
|
||||||
|
Sequence: accSeqs[i],
|
||||||
|
}
|
||||||
|
|
||||||
|
sigsV2 = append(sigsV2, sigV2)
|
||||||
|
}
|
||||||
|
err := suite.txBuilder.SetSignatures(sigsV2...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second round: all signer infos are set, so each signer can sign.
|
||||||
|
sigsV2 = []signing.SignatureV2{}
|
||||||
|
for i, priv := range privs {
|
||||||
|
signerData := xauthsigning.SignerData{
|
||||||
|
ChainID: chainID,
|
||||||
|
AccountNumber: accNums[i],
|
||||||
|
Sequence: accSeqs[i],
|
||||||
|
}
|
||||||
|
sigV2, err := tx.SignWithPrivKey(
|
||||||
|
suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), signerData,
|
||||||
|
suite.txBuilder, priv, suite.clientCtx.TxConfig, accSeqs[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sigsV2 = append(sigsV2, sigV2)
|
||||||
|
}
|
||||||
|
err = suite.txBuilder.SetSignatures(sigsV2...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return suite.txBuilder.GetTx(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCase represents a test case used in test tables.
|
||||||
|
type TestCase struct {
|
||||||
|
desc string
|
||||||
|
malleate func()
|
||||||
|
simulate bool
|
||||||
|
expPass bool
|
||||||
|
expErr error
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateTestTx is a helper function to create a tx given multiple inputs.
|
||||||
|
func (suite *AnteTestSuite) RunTestCase(privs []cryptotypes.PrivKey, msgs []sdk.Msg, feeAmount sdk.Coins, gasLimit uint64, accNums, accSeqs []uint64, chainID string, tc TestCase) {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", tc.desc), func() {
|
||||||
|
suite.Require().NoError(suite.txBuilder.SetMsgs(msgs...))
|
||||||
|
suite.txBuilder.SetFeeAmount(feeAmount)
|
||||||
|
suite.txBuilder.SetGasLimit(gasLimit)
|
||||||
|
|
||||||
|
// Theoretically speaking, ante handler unit tests should only test
|
||||||
|
// ante handlers, but here we sometimes also test the tx creation
|
||||||
|
// process.
|
||||||
|
tx, txErr := suite.CreateTestTx(privs, accNums, accSeqs, chainID)
|
||||||
|
newCtx, anteErr := suite.anteHandler(suite.ctx, tx, tc.simulate)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
suite.Require().NoError(txErr)
|
||||||
|
suite.Require().NoError(anteErr)
|
||||||
|
suite.Require().NotNil(newCtx)
|
||||||
|
|
||||||
|
suite.ctx = newCtx
|
||||||
|
} else {
|
||||||
|
switch {
|
||||||
|
case txErr != nil:
|
||||||
|
suite.Require().Error(txErr)
|
||||||
|
suite.Require().True(errors.Is(txErr, tc.expErr))
|
||||||
|
|
||||||
|
case anteErr != nil:
|
||||||
|
suite.Require().Error(anteErr)
|
||||||
|
suite.Require().True(errors.Is(anteErr, tc.expErr))
|
||||||
|
|
||||||
|
default:
|
||||||
|
suite.Fail("expected one of txErr,anteErr to be an error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAnteTestSuite(t *testing.T) {
|
||||||
|
suite.Run(t, new(AnteTestSuite))
|
||||||
|
}
|
196
x/bond/README.md
Normal file
196
x/bond/README.md
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
# Build chain
|
||||||
|
```bash
|
||||||
|
# it will create binary in build folder with `ethermintd`
|
||||||
|
$ make build
|
||||||
|
```
|
||||||
|
# Setup Chain
|
||||||
|
```bash
|
||||||
|
./build/ethermintd keys add root
|
||||||
|
./build/ethermintd init test-moniker --chain-id ethermint_9000-1
|
||||||
|
./build/ethermintd add-genesis-account $(./build/ethermintd keys show root -a) 1000000000000000000aphoton,1000000000000000000stake
|
||||||
|
./build/ethermintd gentx root 1000000000000000000stake --chain-id ethermint_9000-1
|
||||||
|
./build/ethermintd collect-gentxs
|
||||||
|
./build/ethermintd start
|
||||||
|
```
|
||||||
|
|
||||||
|
# Params
|
||||||
|
```
|
||||||
|
$ ./build/ethermintd q bond params -o json | jq .
|
||||||
|
|
||||||
|
{
|
||||||
|
"params": {
|
||||||
|
"max_bond_amount": {
|
||||||
|
"denom": "stake",
|
||||||
|
"amount": "100000000000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Create Bond
|
||||||
|
```
|
||||||
|
$ ./build/ethermintd tx bond create 100aphoton --from root --chain-id $(./build/ethermintd status | jq .NodeInfo.network -r)
|
||||||
|
|
||||||
|
{"body":{"messages":[{"@type":"/vulcanize.bond.v1beta1.MsgCreateBond","signer":"ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk","coins":[{"denom":"aphoton","amount":"100"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
|
||||||
|
|
||||||
|
confirm transaction before signing and broadcasting [y/N]: y
|
||||||
|
code: 0
|
||||||
|
codespace: ""
|
||||||
|
data: ""
|
||||||
|
gas_used: "0"
|
||||||
|
gas_wanted: "0"
|
||||||
|
height: "0"
|
||||||
|
info: ""
|
||||||
|
logs: []
|
||||||
|
raw_log: '[]'
|
||||||
|
timestamp: ""
|
||||||
|
tx: null
|
||||||
|
txhash: C6D362E11D4C9FB06D620F3CCAF363A69A074297A00E9CAECBDA5BE1CC302EB8
|
||||||
|
```
|
||||||
|
# Refill Bond
|
||||||
|
```
|
||||||
|
$ ./build/ethermintd tx bond refill c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440 1000aphoton --from root --chain-id $(./build/ethermintd status | jq .NodeInfo.network -r)
|
||||||
|
{"body":{"messages":[{"@type":"/vulcanize.bond.v1beta1.MsgRefillBond","id":"c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440","signer":"ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk","coins":[{"denom":"aphoton","amount":"1000"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
|
||||||
|
|
||||||
|
confirm transaction before signing and broadcasting [y/N]: y
|
||||||
|
code: 0
|
||||||
|
codespace: ""
|
||||||
|
data: ""
|
||||||
|
gas_used: "0"
|
||||||
|
gas_wanted: "0"
|
||||||
|
height: "0"
|
||||||
|
info: ""
|
||||||
|
logs: []
|
||||||
|
raw_log: '[]'
|
||||||
|
timestamp: ""
|
||||||
|
tx: null
|
||||||
|
txhash: 025B04E2C923EFE2299CD171B40829CB1FE4D1A69DA7563C64AAC3D5C27BDFC9
|
||||||
|
|
||||||
|
```
|
||||||
|
# Withdraw from bond
|
||||||
|
```
|
||||||
|
$ ./build/ethermintd tx bond withdraw c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440 1000aphoton --from root --chain-id $(./build/ethermintd status | jq .NodeInfo.network -r)
|
||||||
|
{"body":{"messages":[{"@type":"/vulcanize.bond.v1beta1.MsgWithdrawBond","id":"c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440","signer":"ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk","coins":[{"denom":"aphoton","amount":"1000"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
|
||||||
|
|
||||||
|
confirm transaction before signing and broadcasting [y/N]: y
|
||||||
|
code: 0
|
||||||
|
codespace: ""
|
||||||
|
data: ""
|
||||||
|
gas_used: "0"
|
||||||
|
gas_wanted: "0"
|
||||||
|
height: "0"
|
||||||
|
info: ""
|
||||||
|
logs: []
|
||||||
|
raw_log: '[]'
|
||||||
|
timestamp: ""
|
||||||
|
tx: null
|
||||||
|
txhash: 7C5E2FE674577CD6BFFF9F92FCCBC61EDFE8F1A00CE29AC84D58FB8F013D2F03
|
||||||
|
```
|
||||||
|
# List Bond
|
||||||
|
```
|
||||||
|
$ ./build/ethermintd q bond list -o json | jq .
|
||||||
|
{
|
||||||
|
"bonds": [
|
||||||
|
{
|
||||||
|
"id": "c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440",
|
||||||
|
"owner": "ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk",
|
||||||
|
"balance": [
|
||||||
|
{
|
||||||
|
"denom": "aphoton",
|
||||||
|
"amount": "100"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pagination": null
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
# Get Bond by Id
|
||||||
|
```
|
||||||
|
$ ./build/ethermintd q bond get c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440 -o json | jq .
|
||||||
|
{
|
||||||
|
"bond": {
|
||||||
|
"id": "c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440",
|
||||||
|
"owner": "ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk",
|
||||||
|
"balance": [
|
||||||
|
{
|
||||||
|
"denom": "aphoton",
|
||||||
|
"amount": "100"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
# Get Bond Module Balance
|
||||||
|
```
|
||||||
|
$ ./build/ethermintd q bond balance -o json | jq .
|
||||||
|
{
|
||||||
|
"balance": [
|
||||||
|
{
|
||||||
|
"denom": "aphoton",
|
||||||
|
"amount": "100"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Get Bonds By Owner
|
||||||
|
```
|
||||||
|
$ ./build/ethermintd q bond by-owner ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk -o json | jq .
|
||||||
|
{
|
||||||
|
"bonds": [
|
||||||
|
{
|
||||||
|
"id": "c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440",
|
||||||
|
"owner": "ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk",
|
||||||
|
"balance": [
|
||||||
|
{
|
||||||
|
"denom": "aphoton",
|
||||||
|
"amount": "100"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pagination": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Cancel the bond
|
||||||
|
```
|
||||||
|
$ ./build/ethermintd tx bond cancel c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440 --from root --chain-id $(./build/ethermintd status | jq .NodeInfo.network -r)
|
||||||
|
{"body":{"messages":[{"@type":"/vulcanize.bond.v1beta1.MsgCancelBond","id":"c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440","signer":"ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
|
||||||
|
|
||||||
|
confirm transaction before signing and broadcasting [y/N]: y
|
||||||
|
code: 0
|
||||||
|
codespace: ""
|
||||||
|
data: ""
|
||||||
|
gas_used: "0"
|
||||||
|
gas_wanted: "0"
|
||||||
|
height: "0"
|
||||||
|
info: ""
|
||||||
|
logs: []
|
||||||
|
raw_log: '[]'
|
||||||
|
timestamp: ""
|
||||||
|
tx: null
|
||||||
|
txhash: 06440D0B35A862E3A6783E147F0E1CDD3374870DAE07E471D465E2830DAF7044
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Note : After the bond create and withdraw bond and cancel bond , account amount needs change as per module
|
||||||
|
```
|
||||||
|
$ ./build/ethermintd q bank balances $(./build/ethermintd keys show root -a) -o json | jq .
|
||||||
|
{
|
||||||
|
"balances": [
|
||||||
|
{
|
||||||
|
"denom": "aphoton",
|
||||||
|
"amount": "1000000000000000000"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pagination": {
|
||||||
|
"next_key": null,
|
||||||
|
"total": "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
17
x/bond/abci.go
Normal file
17
x/bond/abci.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package bond
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
"github.com/tharsis/ethermint/x/bond/keeper"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BeginBlocker will persist the current header and validator set as a historical entry
|
||||||
|
// and prune the oldest entry based on the HistoricalEntries parameter
|
||||||
|
func BeginBlocker(ctx sdk.Context, k keeper.Keeper) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// EndBlocker Called every block, update validator set
|
||||||
|
func EndBlocker(ctx sdk.Context, k keeper.Keeper) []abci.ValidatorUpdate {
|
||||||
|
return []abci.ValidatorUpdate{}
|
||||||
|
}
|
203
x/bond/client/cli/query.go
Normal file
203
x/bond/client/cli/query.go
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
|
"github.com/cosmos/cosmos-sdk/version"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/tharsis/ethermint/x/bond/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetQueryCmd returns the cli query commands for this module
|
||||||
|
func GetQueryCmd() *cobra.Command {
|
||||||
|
bondQueryCmd := &cobra.Command{
|
||||||
|
Use: types.ModuleName,
|
||||||
|
Short: "Querying commands for the bond module",
|
||||||
|
DisableFlagParsing: true,
|
||||||
|
SuggestionsMinimumDistance: 2,
|
||||||
|
RunE: client.ValidateCmd,
|
||||||
|
}
|
||||||
|
|
||||||
|
bondQueryCmd.AddCommand(
|
||||||
|
GetQueryParamsCmd(),
|
||||||
|
GetQueryBondLists(),
|
||||||
|
GetBondByIdCmd(),
|
||||||
|
GetBondListByOwnerCmd(),
|
||||||
|
GetBondModuleBalanceCmd(),
|
||||||
|
)
|
||||||
|
|
||||||
|
return bondQueryCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetQueryParamsCmd implements the params query command.
|
||||||
|
func GetQueryParamsCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "params",
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
Short: "Query the current bond parameters information.",
|
||||||
|
Long: strings.TrimSpace(
|
||||||
|
fmt.Sprintf(`Query values set as bond parameters.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
$ %s query %s params
|
||||||
|
`,
|
||||||
|
version.AppName, types.ModuleName,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
queryClient := types.NewQueryClient(clientCtx)
|
||||||
|
res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientCtx.PrintProto(res)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
flags.AddQueryFlagsToCmd(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetQueryBondLists implements the bond lists query command.
|
||||||
|
func GetQueryBondLists() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "list",
|
||||||
|
Short: "List bonds.",
|
||||||
|
Long: strings.TrimSpace(
|
||||||
|
fmt.Sprintf(`Get bond list .
|
||||||
|
|
||||||
|
Example:
|
||||||
|
$ %s query %s list
|
||||||
|
`,
|
||||||
|
version.AppName, types.ModuleName,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
queryClient := types.NewQueryClient(clientCtx)
|
||||||
|
res, err := queryClient.Bonds(cmd.Context(), &types.QueryGetBondsRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientCtx.PrintProto(res)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
flags.AddQueryFlagsToCmd(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBondByIdCmd implements the bond info by id query command.
|
||||||
|
func GetBondByIdCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "get [bond Id]",
|
||||||
|
Short: "Get bond.",
|
||||||
|
Long: strings.TrimSpace(
|
||||||
|
fmt.Sprintf(`Get bond info by bond id .
|
||||||
|
|
||||||
|
Example:
|
||||||
|
$ %s query bond get {BOND ID}
|
||||||
|
`,
|
||||||
|
version.AppName,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
queryClient := types.NewQueryClient(clientCtx)
|
||||||
|
|
||||||
|
id := args[0]
|
||||||
|
|
||||||
|
res, err := queryClient.GetBondById(cmd.Context(), &types.QueryGetBondByIdRequest{Id: id})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientCtx.PrintProto(res)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
flags.AddQueryFlagsToCmd(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBondListByOwnerCmd queries the bond list by owner.
|
||||||
|
func GetBondListByOwnerCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "by-owner [address]",
|
||||||
|
Short: "Query bonds by owner.",
|
||||||
|
Long: strings.TrimSpace(
|
||||||
|
fmt.Sprintf(`Get bond list by owner.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
$ %s query %s query-by-owner [address]
|
||||||
|
`,
|
||||||
|
version.AppName, types.ModuleName,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
queryClient := types.NewQueryClient(clientCtx)
|
||||||
|
owner := args[0]
|
||||||
|
res, err := queryClient.GetBondsByOwner(cmd.Context(), &types.QueryGetBondsByOwnerRequest{Owner: owner})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientCtx.PrintProto(res)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
flags.AddQueryFlagsToCmd(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBondModuleBalanceCmd queries the bond module account balance.
|
||||||
|
func GetBondModuleBalanceCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "balance",
|
||||||
|
Short: "Get bond module account balance.",
|
||||||
|
Long: strings.TrimSpace(
|
||||||
|
fmt.Sprintf(`Get bond module balance.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
$ %s query %s balance
|
||||||
|
`,
|
||||||
|
version.AppName, types.ModuleName,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
queryClient := types.NewQueryClient(clientCtx)
|
||||||
|
|
||||||
|
res, err := queryClient.GetBondsModuleBalance(cmd.Context(), &types.QueryGetBondModuleBalanceRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientCtx.PrintProto(res)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
flags.AddQueryFlagsToCmd(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
125
x/bond/client/cli/tx.go
Normal file
125
x/bond/client/cli/tx.go
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/tharsis/ethermint/server/flags"
|
||||||
|
"github.com/tharsis/ethermint/x/bond/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewTxCmd returns a root CLI command handler for all x/bond transaction commands.
|
||||||
|
func NewTxCmd() *cobra.Command {
|
||||||
|
bondTxCmd := &cobra.Command{
|
||||||
|
Use: types.ModuleName,
|
||||||
|
Short: "bond transaction subcommands",
|
||||||
|
DisableFlagParsing: true,
|
||||||
|
SuggestionsMinimumDistance: 2,
|
||||||
|
RunE: client.ValidateCmd,
|
||||||
|
}
|
||||||
|
|
||||||
|
bondTxCmd.AddCommand(
|
||||||
|
NewCreateBondCmd(),
|
||||||
|
RefillBondCmd(),
|
||||||
|
WithdrawBondCmd(),
|
||||||
|
CancelBondCmd(),
|
||||||
|
)
|
||||||
|
|
||||||
|
return bondTxCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCreateBondCmd is the CLI command for creating a bond.
|
||||||
|
func NewCreateBondCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "create [amount]",
|
||||||
|
Short: "Create bond.",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientTxContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
coin, err := sdk.ParseCoinNormalized(args[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := types.NewMsgCreateBond(sdk.NewCoins(coin), clientCtx.GetFromAddress())
|
||||||
|
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.AddTxFlags(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// RefillBondCmd is the CLI command for creating a bond.
|
||||||
|
func RefillBondCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "refill [bond Id] [amount]",
|
||||||
|
Short: "Refill bond.",
|
||||||
|
Args: cobra.ExactArgs(2),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientTxContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
bondId := args[0]
|
||||||
|
coin, err := sdk.ParseCoinNormalized(args[1])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := types.NewMsgRefillBond(bondId, coin, clientCtx.GetFromAddress())
|
||||||
|
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
flags.AddTxFlags(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithdrawBondCmd is the CLI command for withdrawing funds from a bond.
|
||||||
|
func WithdrawBondCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "withdraw [bond Id] [amount]",
|
||||||
|
Short: "Withdraw amount from bond.",
|
||||||
|
Args: cobra.ExactArgs(2),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientTxContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
bondId := args[0]
|
||||||
|
coin, err := sdk.ParseCoinNormalized(args[1])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := types.NewMsgWithdrawBond(bondId, coin, clientCtx.GetFromAddress())
|
||||||
|
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
flags.AddTxFlags(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelBondCmd is the CLI command for cancelling a bond.
|
||||||
|
func CancelBondCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "cancel [bond Id]",
|
||||||
|
Short: "cancel bond.",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
clientCtx, err := client.GetClientTxContext(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
bondId := args[0]
|
||||||
|
msg := types.NewMsgCancelBond(bondId, clientCtx.GetFromAddress())
|
||||||
|
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
flags.AddTxFlags(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
13
x/bond/client/testutil/cli_test.go
Normal file
13
x/bond/client/testutil/cli_test.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package testutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
"github.com/tharsis/ethermint/testutil/network"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIntegrationTestSuite(t *testing.T) {
|
||||||
|
cfg := network.DefaultConfig()
|
||||||
|
cfg.NumValidators = 1
|
||||||
|
suite.Run(t, NewIntegrationTestSuite(cfg))
|
||||||
|
}
|
213
x/bond/client/testutil/grpc.go
Normal file
213
x/bond/client/testutil/grpc.go
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
package testutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/rest"
|
||||||
|
tmcli "github.com/tendermint/tendermint/libs/cli"
|
||||||
|
"github.com/tharsis/ethermint/x/bond/client/cli"
|
||||||
|
bondtypes "github.com/tharsis/ethermint/x/bond/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) TestGRPCGetBonds() {
|
||||||
|
val := s.network.Validators[0]
|
||||||
|
sr := s.Require()
|
||||||
|
reqUrl := fmt.Sprintf("%s/vulcanize/bond/v1beta1/bonds", val.APIAddress)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
url string
|
||||||
|
expErr bool
|
||||||
|
errorMsg string
|
||||||
|
preRun func()
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"invalid request with headers",
|
||||||
|
reqUrl + "asdasdas",
|
||||||
|
true,
|
||||||
|
"",
|
||||||
|
func() {
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valid request",
|
||||||
|
reqUrl,
|
||||||
|
false,
|
||||||
|
"",
|
||||||
|
func() {
|
||||||
|
s.createBond()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
s.Run(tc.name, func() {
|
||||||
|
resp, _ := rest.GetRequest(tc.url)
|
||||||
|
if tc.expErr {
|
||||||
|
sr.Contains(string(resp), tc.errorMsg)
|
||||||
|
} else {
|
||||||
|
var response bondtypes.QueryGetBondsResponse
|
||||||
|
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.NotZero(len(response.GetBonds()))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) TestGRPCGetParams() {
|
||||||
|
val := s.network.Validators[0]
|
||||||
|
sr := s.Require()
|
||||||
|
reqUrl := fmt.Sprintf("%s/vulcanize/bond/v1beta1/params", val.APIAddress)
|
||||||
|
|
||||||
|
resp, err := rest.GetRequest(reqUrl)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
var params bondtypes.QueryParamsResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(resp, ¶ms)
|
||||||
|
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.Equal(params.GetParams().MaxBondAmount, bondtypes.DefaultParams().MaxBondAmount)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) TestGRPCGetBondsByOwner() {
|
||||||
|
val := s.network.Validators[0]
|
||||||
|
sr := s.Require()
|
||||||
|
reqUrl := val.APIAddress + "/vulcanize/bond/v1beta1/by-owner/%s"
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
url string
|
||||||
|
expErr bool
|
||||||
|
preRun func()
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"empty list",
|
||||||
|
fmt.Sprintf(reqUrl, "asdasd"),
|
||||||
|
true,
|
||||||
|
func() {
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valid request",
|
||||||
|
fmt.Sprintf(reqUrl, s.accountAddress),
|
||||||
|
false,
|
||||||
|
func() {
|
||||||
|
s.createBond()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
s.Run(tc.name, func() {
|
||||||
|
if !tc.expErr {
|
||||||
|
tc.preRun()
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := rest.GetRequest(tc.url)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
var bonds bondtypes.QueryGetBondsByOwnerResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &bonds)
|
||||||
|
sr.NoError(err)
|
||||||
|
if tc.expErr {
|
||||||
|
sr.Empty(bonds.GetBonds())
|
||||||
|
} else {
|
||||||
|
bondsList := bonds.GetBonds()
|
||||||
|
sr.NotZero(len(bondsList))
|
||||||
|
sr.Equal(s.accountAddress, bondsList[0].GetOwner())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) TestGRPCGetBondById() {
|
||||||
|
val := s.network.Validators[0]
|
||||||
|
sr := s.Require()
|
||||||
|
reqUrl := val.APIAddress + "/vulcanize/bond/v1beta1/bonds/%s"
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
url string
|
||||||
|
expErr bool
|
||||||
|
preRun func() string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"invalid request",
|
||||||
|
fmt.Sprintf(reqUrl, "asdadad"),
|
||||||
|
true,
|
||||||
|
func() string {
|
||||||
|
return ""
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valid request",
|
||||||
|
reqUrl,
|
||||||
|
false,
|
||||||
|
func() string {
|
||||||
|
// creating the bond
|
||||||
|
s.createBond()
|
||||||
|
|
||||||
|
// getting the bonds list and returning the bond-id
|
||||||
|
clientCtx := val.ClientCtx
|
||||||
|
cmd := cli.GetQueryBondLists()
|
||||||
|
args := []string{
|
||||||
|
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
|
||||||
|
}
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
||||||
|
sr.NoError(err)
|
||||||
|
var queryResponse bondtypes.QueryGetBondsResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
|
||||||
|
sr.NoError(err)
|
||||||
|
|
||||||
|
// extract bond id from bonds list
|
||||||
|
bond := queryResponse.GetBonds()[0]
|
||||||
|
return bond.GetId()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
s.Run(tc.name, func() {
|
||||||
|
var bondId string
|
||||||
|
if !tc.expErr {
|
||||||
|
bondId = tc.preRun()
|
||||||
|
tc.url = fmt.Sprintf(reqUrl, bondId)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := rest.GetRequest(tc.url)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
var bonds bondtypes.QueryGetBondByIdResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &bonds)
|
||||||
|
|
||||||
|
if tc.expErr {
|
||||||
|
sr.Empty(bonds.GetBond().GetId())
|
||||||
|
} else {
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.NotZero(bonds.GetBond().GetId())
|
||||||
|
sr.Equal(bonds.GetBond().GetId(), bondId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) TestGRPCGetBondModuleBalance() {
|
||||||
|
val := s.network.Validators[0]
|
||||||
|
sr := s.Require()
|
||||||
|
reqUrl := fmt.Sprintf("%s/vulcanize/bond/v1beta1/balance", val.APIAddress)
|
||||||
|
|
||||||
|
// creating the bond
|
||||||
|
s.createBond()
|
||||||
|
|
||||||
|
s.Run("valid request", func() {
|
||||||
|
resp, err := rest.GetRequest(reqUrl)
|
||||||
|
sr.NoError(err)
|
||||||
|
|
||||||
|
var response bondtypes.QueryGetBondModuleBalanceResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
|
||||||
|
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.False(response.GetBalance().IsZero())
|
||||||
|
})
|
||||||
|
}
|
331
x/bond/client/testutil/query.go
Normal file
331
x/bond/client/testutil/query.go
Normal file
@ -0,0 +1,331 @@
|
|||||||
|
package testutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||||
|
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
tmcli "github.com/tendermint/tendermint/libs/cli"
|
||||||
|
"github.com/tharsis/ethermint/testutil/network"
|
||||||
|
"github.com/tharsis/ethermint/x/bond/client/cli"
|
||||||
|
"github.com/tharsis/ethermint/x/bond/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IntegrationTestSuite struct {
|
||||||
|
suite.Suite
|
||||||
|
|
||||||
|
cfg network.Config
|
||||||
|
network *network.Network
|
||||||
|
accountName string
|
||||||
|
accountAddress string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
|
||||||
|
return &IntegrationTestSuite{cfg: cfg}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) SetupSuite() {
|
||||||
|
s.T().Log("setting up integration test suite")
|
||||||
|
|
||||||
|
s.network = network.New(s.T(), s.cfg)
|
||||||
|
|
||||||
|
_, err := s.network.WaitForHeight(1)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
s.accountName = "accountName"
|
||||||
|
// setting up random account
|
||||||
|
s.createAccountWithBalance(s.accountName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) TearDownSuite() {
|
||||||
|
s.T().Log("tearing down integration test suite")
|
||||||
|
s.network.Cleanup()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) TestGetCmdQueryParams() {
|
||||||
|
val := s.network.Validators[0]
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
args []string
|
||||||
|
outputType string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"json output",
|
||||||
|
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
|
||||||
|
"json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
s.Run(tc.name, func() {
|
||||||
|
cmd := cli.GetQueryParamsCmd()
|
||||||
|
clientCtx := val.ClientCtx
|
||||||
|
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
var response types.QueryParamsResponse
|
||||||
|
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Equal(response.Params.MaxBondAmount, types.DefaultParams().MaxBondAmount)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) createAccountWithBalance(accountName string) {
|
||||||
|
val := s.network.Validators[0]
|
||||||
|
sr := s.Require()
|
||||||
|
consPrivKey := ed25519.GenPrivKey()
|
||||||
|
consPubKeyBz, err := s.cfg.Codec.MarshalInterfaceJSON(consPrivKey.PubKey())
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.NotNil(consPubKeyBz)
|
||||||
|
|
||||||
|
info, _, err := val.ClientCtx.Keyring.NewMnemonic(accountName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
|
||||||
|
sr.NoError(err)
|
||||||
|
|
||||||
|
newAddr := sdk.AccAddress(info.GetPubKey().Address())
|
||||||
|
_, err = banktestutil.MsgSendExec(
|
||||||
|
val.ClientCtx,
|
||||||
|
val.Address,
|
||||||
|
newAddr,
|
||||||
|
sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))),
|
||||||
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||||
|
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
|
||||||
|
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||||
|
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||||
|
)
|
||||||
|
sr.NoError(err)
|
||||||
|
s.accountAddress = newAddr.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) createBond() {
|
||||||
|
val := s.network.Validators[0]
|
||||||
|
sr := s.Require()
|
||||||
|
createBondCmd := cli.NewCreateBondCmd()
|
||||||
|
args := []string{
|
||||||
|
fmt.Sprintf("10%s", s.cfg.BondDenom),
|
||||||
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, s.accountName),
|
||||||
|
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
|
||||||
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||||
|
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||||
|
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
|
||||||
|
}
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, createBondCmd, args)
|
||||||
|
sr.NoError(err)
|
||||||
|
var d sdk.TxResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.Zero(d.Code)
|
||||||
|
err = s.network.WaitForNextBlock()
|
||||||
|
sr.NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) TestGetQueryBondLists() {
|
||||||
|
val := s.network.Validators[0]
|
||||||
|
sr := s.Require()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
args []string
|
||||||
|
createBond bool
|
||||||
|
preRun func()
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"create and get bond lists",
|
||||||
|
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
|
||||||
|
true,
|
||||||
|
func() {
|
||||||
|
s.createBond()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||||
|
clientCtx := val.ClientCtx
|
||||||
|
if tc.createBond {
|
||||||
|
tc.preRun()
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := cli.GetQueryBondLists()
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
|
||||||
|
sr.NoError(err)
|
||||||
|
var queryResponse types.QueryGetBondsResponse
|
||||||
|
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.NotZero(len(queryResponse.GetBonds()))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) TestGetQueryBondById() {
|
||||||
|
val := s.network.Validators[0]
|
||||||
|
sr := s.Require()
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
args []string
|
||||||
|
err bool
|
||||||
|
preRun func() string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"invalid bond id",
|
||||||
|
[]string{
|
||||||
|
fmt.Sprint("not_found_bond_id"),
|
||||||
|
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
func() string {
|
||||||
|
return ""
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create and get bond by id",
|
||||||
|
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
|
||||||
|
false,
|
||||||
|
func() string {
|
||||||
|
// creating the bond
|
||||||
|
s.createBond()
|
||||||
|
|
||||||
|
// getting the bonds list and returning the bond-id
|
||||||
|
clientCtx := val.ClientCtx
|
||||||
|
cmd := cli.GetQueryBondLists()
|
||||||
|
args := []string{
|
||||||
|
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
|
||||||
|
}
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
||||||
|
sr.NoError(err)
|
||||||
|
var queryResponse types.QueryGetBondsResponse
|
||||||
|
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
|
||||||
|
sr.NoError(err)
|
||||||
|
|
||||||
|
// extract bond id from bonds list
|
||||||
|
bond := queryResponse.GetBonds()[0]
|
||||||
|
return bond.GetId()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||||
|
clientCtx := val.ClientCtx
|
||||||
|
if !tc.err {
|
||||||
|
bondId := tc.preRun()
|
||||||
|
tc.args = append([]string{bondId}, tc.args...)
|
||||||
|
}
|
||||||
|
cmd := cli.GetBondByIdCmd()
|
||||||
|
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
|
||||||
|
sr.NoError(err)
|
||||||
|
var queryResponse types.QueryGetBondByIdResponse
|
||||||
|
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
|
||||||
|
sr.NoError(err)
|
||||||
|
if tc.err {
|
||||||
|
sr.Zero(len(queryResponse.GetBond().GetId()))
|
||||||
|
} else {
|
||||||
|
sr.NotZero(len(queryResponse.GetBond().GetId()))
|
||||||
|
sr.Equal(s.accountAddress, queryResponse.GetBond().GetOwner())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) TestGetQueryBondListsByOwner() {
|
||||||
|
val := s.network.Validators[0]
|
||||||
|
sr := s.Require()
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
args []string
|
||||||
|
err bool
|
||||||
|
preRun func()
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"invalid owner address",
|
||||||
|
[]string{
|
||||||
|
fmt.Sprint("not_found_bond_id"),
|
||||||
|
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
func() {
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"get bond lists by owner address",
|
||||||
|
[]string{
|
||||||
|
fmt.Sprint(s.accountAddress),
|
||||||
|
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
func() {
|
||||||
|
s.createBond()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||||
|
clientCtx := val.ClientCtx
|
||||||
|
if !tc.err {
|
||||||
|
tc.preRun()
|
||||||
|
}
|
||||||
|
cmd := cli.GetBondListByOwnerCmd()
|
||||||
|
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
|
||||||
|
sr.NoError(err)
|
||||||
|
var queryResponse types.QueryGetBondsByOwnerResponse
|
||||||
|
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
|
||||||
|
sr.NoError(err)
|
||||||
|
if tc.err {
|
||||||
|
sr.Zero(len(queryResponse.GetBonds()))
|
||||||
|
} else {
|
||||||
|
sr.NotZero(len(queryResponse.GetBonds()))
|
||||||
|
sr.Equal(s.accountAddress, queryResponse.GetBonds()[0].GetOwner())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationTestSuite) TestGetQueryBondModuleBalance() {
|
||||||
|
val := s.network.Validators[0]
|
||||||
|
sr := s.Require()
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
args []string
|
||||||
|
err bool
|
||||||
|
preRun func()
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"get bond module balance",
|
||||||
|
[]string{
|
||||||
|
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
func() {
|
||||||
|
s.createBond()
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||||
|
clientCtx := val.ClientCtx
|
||||||
|
if !tc.err {
|
||||||
|
tc.preRun()
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := cli.GetBondModuleBalanceCmd()
|
||||||
|
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
|
||||||
|
sr.NoError(err)
|
||||||
|
var queryResponse types.QueryGetBondModuleBalanceResponse
|
||||||
|
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
|
||||||
|
sr.NoError(err)
|
||||||
|
sr.False(queryResponse.GetBalance().IsZero())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user