mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 01:47:27 +00:00 
			
		
		
		
	merge release v0.12.1 updates (#724)
* use kava antehandler * add authenticated mempool decorator * add get authorised address methods * hook antehandler into app * refactor address fetcher interface * tidy up args to NewApp * remove unused function * tidy up after removing address fetcher interface * read authorized addresses from config * fix error message, and minor tidy * update cosmos-sdk and tendermint * clarify function name * add flags for mempool options
This commit is contained in:
		
							parent
							
								
									9472c09b91
								
							
						
					
					
						commit
						9c69ee2fbf
					
				
							
								
								
									
										32
									
								
								app/ante/ante.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/ante/ante.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					package ante
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/x/auth/ante"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/x/auth/keeper"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/x/auth/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewAnteHandler returns an 'AnteHandler' that will run actions before a tx is sent to a module's handler.
 | 
				
			||||||
 | 
					func NewAnteHandler(ak keeper.AccountKeeper, supplyKeeper types.SupplyKeeper, sigGasConsumer ante.SignatureVerificationGasConsumer, addressFetchers ...AddressFetcher) sdk.AnteHandler {
 | 
				
			||||||
 | 
						decorators := []sdk.AnteDecorator{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						decorators = append(decorators, ante.NewSetUpContextDecorator()) // outermost AnteDecorator. SetUpContext must be called first
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(addressFetchers) > 0 {
 | 
				
			||||||
 | 
							decorators = append(decorators, NewAuthenticatedMempoolDecorator(addressFetchers...))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						decorators = append(decorators,
 | 
				
			||||||
 | 
							ante.NewMempoolFeeDecorator(),
 | 
				
			||||||
 | 
							ante.NewValidateBasicDecorator(),
 | 
				
			||||||
 | 
							ante.NewValidateMemoDecorator(ak),
 | 
				
			||||||
 | 
							ante.NewConsumeGasForTxSizeDecorator(ak),
 | 
				
			||||||
 | 
							ante.NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators
 | 
				
			||||||
 | 
							ante.NewValidateSigCountDecorator(ak),
 | 
				
			||||||
 | 
							ante.NewDeductFeeDecorator(ak, supplyKeeper),
 | 
				
			||||||
 | 
							ante.NewSigGasConsumeDecorator(ak, sigGasConsumer),
 | 
				
			||||||
 | 
							ante.NewSigVerificationDecorator(ak),
 | 
				
			||||||
 | 
							ante.NewIncrementSequenceDecorator(ak), // innermost AnteDecorator
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						return sdk.ChainAnteDecorators(decorators...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										202
									
								
								app/ante/ante_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								app/ante/ante_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,202 @@
 | 
				
			|||||||
 | 
					package ante_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/simapp/helpers"
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/x/auth"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/x/bank"
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/require"
 | 
				
			||||||
 | 
						abci "github.com/tendermint/tendermint/abci/types"
 | 
				
			||||||
 | 
						"github.com/tendermint/tendermint/crypto"
 | 
				
			||||||
 | 
						"github.com/tendermint/tendermint/libs/log"
 | 
				
			||||||
 | 
						tmdb "github.com/tendermint/tm-db"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/app"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/bep3"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/pricefeed"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAppAnteHandler(t *testing.T) {
 | 
				
			||||||
 | 
						testPrivKeys, testAddresses := app.GeneratePrivKeyAddressPairs(10)
 | 
				
			||||||
 | 
						unauthed := testAddresses[0:2]
 | 
				
			||||||
 | 
						unathedKeys := testPrivKeys[0:2]
 | 
				
			||||||
 | 
						deputy := testAddresses[2]
 | 
				
			||||||
 | 
						deputyKey := testPrivKeys[2]
 | 
				
			||||||
 | 
						oracles := testAddresses[3:6]
 | 
				
			||||||
 | 
						oraclesKeys := testPrivKeys[3:6]
 | 
				
			||||||
 | 
						manual := testAddresses[6:]
 | 
				
			||||||
 | 
						manualKeys := testPrivKeys[6:]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						db := tmdb.NewMemDB()
 | 
				
			||||||
 | 
						tApp := app.TestApp{
 | 
				
			||||||
 | 
							App: *app.NewApp(log.NewNopLogger(), db, nil,
 | 
				
			||||||
 | 
								app.AppOptions{
 | 
				
			||||||
 | 
									MempoolEnableAuth:    true,
 | 
				
			||||||
 | 
									MempoolAuthAddresses: manual,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						chainID := "internal-test-chain"
 | 
				
			||||||
 | 
						tApp = tApp.InitializeFromGenesisStatesWithTimeAndChainID(
 | 
				
			||||||
 | 
							time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
				
			||||||
 | 
							chainID,
 | 
				
			||||||
 | 
							NewAuthGenStateWithSameCoins(
 | 
				
			||||||
 | 
								sdk.NewCoins(sdk.NewInt64Coin("ukava", 1_000_000_000)),
 | 
				
			||||||
 | 
								testAddresses,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							newBep3GenStateMulti(deputy),
 | 
				
			||||||
 | 
							newPricefeedGenStateMulti(oracles),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						testcases := []struct {
 | 
				
			||||||
 | 
							name       string
 | 
				
			||||||
 | 
							address    sdk.AccAddress
 | 
				
			||||||
 | 
							privKey    crypto.PrivKey
 | 
				
			||||||
 | 
							expectPass bool
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:       "unauthorized",
 | 
				
			||||||
 | 
								address:    unauthed[1],
 | 
				
			||||||
 | 
								privKey:    unathedKeys[1],
 | 
				
			||||||
 | 
								expectPass: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:       "oracle",
 | 
				
			||||||
 | 
								address:    oracles[1],
 | 
				
			||||||
 | 
								privKey:    oraclesKeys[1],
 | 
				
			||||||
 | 
								expectPass: true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:       "deputy",
 | 
				
			||||||
 | 
								address:    deputy,
 | 
				
			||||||
 | 
								privKey:    deputyKey,
 | 
				
			||||||
 | 
								expectPass: true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:       "manual",
 | 
				
			||||||
 | 
								address:    manual[1],
 | 
				
			||||||
 | 
								privKey:    manualKeys[1],
 | 
				
			||||||
 | 
								expectPass: true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range testcases {
 | 
				
			||||||
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
 | 
								stdTx := helpers.GenTx(
 | 
				
			||||||
 | 
									[]sdk.Msg{
 | 
				
			||||||
 | 
										bank.NewMsgSend(
 | 
				
			||||||
 | 
											tc.address,
 | 
				
			||||||
 | 
											testAddresses[0],
 | 
				
			||||||
 | 
											sdk.NewCoins(sdk.NewInt64Coin("ukava", 1_000_000)),
 | 
				
			||||||
 | 
										),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									sdk.NewCoins(), // no fee
 | 
				
			||||||
 | 
									helpers.DefaultGenTxGas,
 | 
				
			||||||
 | 
									chainID,
 | 
				
			||||||
 | 
									[]uint64{0},
 | 
				
			||||||
 | 
									[]uint64{0}, // fixed sequence numbers will cause tests to fail sig verification if the same address is used twice
 | 
				
			||||||
 | 
									tc.privKey,
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
								txBytes, err := auth.DefaultTxEncoder(tApp.Codec())(stdTx)
 | 
				
			||||||
 | 
								require.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								res := tApp.CheckTx(
 | 
				
			||||||
 | 
									abci.RequestCheckTx{
 | 
				
			||||||
 | 
										Tx:   txBytes,
 | 
				
			||||||
 | 
										Type: abci.CheckTxType_New,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if tc.expectPass {
 | 
				
			||||||
 | 
									require.Zero(t, res.Code, res.Log)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									require.NotZero(t, res.Code)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewAuthGenStateWithSameCoins(coins sdk.Coins, addresses []sdk.AccAddress) app.GenesisState {
 | 
				
			||||||
 | 
						coinsList := make([]sdk.Coins, len(addresses))
 | 
				
			||||||
 | 
						for i := range addresses {
 | 
				
			||||||
 | 
							coinsList[i] = coins
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return app.NewAuthGenState(addresses, coinsList)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newPricefeedGenStateMulti(oracles []sdk.AccAddress) app.GenesisState {
 | 
				
			||||||
 | 
						pfGenesis := pricefeed.GenesisState{
 | 
				
			||||||
 | 
							Params: pricefeed.Params{
 | 
				
			||||||
 | 
								Markets: []pricefeed.Market{
 | 
				
			||||||
 | 
									{MarketID: "btc:usd", BaseAsset: "btc", QuoteAsset: "usd", Oracles: oracles, Active: true},
 | 
				
			||||||
 | 
									{MarketID: "xrp:usd", BaseAsset: "xrp", QuoteAsset: "usd", Oracles: oracles, Active: true},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return app.GenesisState{pricefeed.ModuleName: pricefeed.ModuleCdc.MustMarshalJSON(pfGenesis)}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newBep3GenStateMulti(deputyAddress sdk.AccAddress) app.GenesisState {
 | 
				
			||||||
 | 
						bep3Genesis := bep3.GenesisState{
 | 
				
			||||||
 | 
							Params: bep3.Params{
 | 
				
			||||||
 | 
								AssetParams: bep3.AssetParams{
 | 
				
			||||||
 | 
									bep3.AssetParam{
 | 
				
			||||||
 | 
										Denom:  "bnb",
 | 
				
			||||||
 | 
										CoinID: 714,
 | 
				
			||||||
 | 
										SupplyLimit: bep3.SupplyLimit{
 | 
				
			||||||
 | 
											Limit:          sdk.NewInt(350000000000000),
 | 
				
			||||||
 | 
											TimeLimited:    false,
 | 
				
			||||||
 | 
											TimeBasedLimit: sdk.ZeroInt(),
 | 
				
			||||||
 | 
											TimePeriod:     time.Hour,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										Active:        true,
 | 
				
			||||||
 | 
										DeputyAddress: deputyAddress,
 | 
				
			||||||
 | 
										FixedFee:      sdk.NewInt(1000),
 | 
				
			||||||
 | 
										MinSwapAmount: sdk.OneInt(),
 | 
				
			||||||
 | 
										MaxSwapAmount: sdk.NewInt(1000000000000),
 | 
				
			||||||
 | 
										MinBlockLock:  bep3.DefaultMinBlockLock,
 | 
				
			||||||
 | 
										MaxBlockLock:  bep3.DefaultMaxBlockLock,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									bep3.AssetParam{
 | 
				
			||||||
 | 
										Denom:  "inc",
 | 
				
			||||||
 | 
										CoinID: 9999,
 | 
				
			||||||
 | 
										SupplyLimit: bep3.SupplyLimit{
 | 
				
			||||||
 | 
											Limit:          sdk.NewInt(100000000000000),
 | 
				
			||||||
 | 
											TimeLimited:    true,
 | 
				
			||||||
 | 
											TimeBasedLimit: sdk.NewInt(50000000000),
 | 
				
			||||||
 | 
											TimePeriod:     time.Hour,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										Active:        false,
 | 
				
			||||||
 | 
										DeputyAddress: deputyAddress,
 | 
				
			||||||
 | 
										FixedFee:      sdk.NewInt(1000),
 | 
				
			||||||
 | 
										MinSwapAmount: sdk.OneInt(),
 | 
				
			||||||
 | 
										MaxSwapAmount: sdk.NewInt(100000000000),
 | 
				
			||||||
 | 
										MinBlockLock:  bep3.DefaultMinBlockLock,
 | 
				
			||||||
 | 
										MaxBlockLock:  bep3.DefaultMaxBlockLock,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Supplies: bep3.AssetSupplies{
 | 
				
			||||||
 | 
								bep3.NewAssetSupply(
 | 
				
			||||||
 | 
									sdk.NewCoin("bnb", sdk.ZeroInt()),
 | 
				
			||||||
 | 
									sdk.NewCoin("bnb", sdk.ZeroInt()),
 | 
				
			||||||
 | 
									sdk.NewCoin("bnb", sdk.ZeroInt()),
 | 
				
			||||||
 | 
									sdk.NewCoin("bnb", sdk.ZeroInt()),
 | 
				
			||||||
 | 
									time.Duration(0),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								bep3.NewAssetSupply(
 | 
				
			||||||
 | 
									sdk.NewCoin("inc", sdk.ZeroInt()),
 | 
				
			||||||
 | 
									sdk.NewCoin("inc", sdk.ZeroInt()),
 | 
				
			||||||
 | 
									sdk.NewCoin("inc", sdk.ZeroInt()),
 | 
				
			||||||
 | 
									sdk.NewCoin("inc", sdk.ZeroInt()),
 | 
				
			||||||
 | 
									time.Duration(0),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							PreviousBlockTime: bep3.DefaultPreviousBlockTime,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return app.GenesisState{bep3.ModuleName: bep3.ModuleCdc.MustMarshalJSON(bep3Genesis)}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										63
									
								
								app/ante/authorized.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								app/ante/authorized.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					package ante
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 | 
				
			||||||
 | 
						authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ sigVerifiableTx = (*authtypes.StdTx)(nil) // assert StdTx implements SigVerifiableTx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SigVerifiableTx defines a Tx interface for all signature verification decorators
 | 
				
			||||||
 | 
					type sigVerifiableTx interface {
 | 
				
			||||||
 | 
						GetSigners() []sdk.AccAddress
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AddressFetcher is a type signature for functions used by the AuthenticatedMempoolDecorator to get authorized addresses.
 | 
				
			||||||
 | 
					type AddressFetcher func(sdk.Context) []sdk.AccAddress
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AuthenticatedMempoolDecorator blocks all txs from reaching the mempool unless they're signed by one of the authorzed addresses.
 | 
				
			||||||
 | 
					// It only runs before entry to mempool (CheckTx), and not in consensus (DeliverTx)
 | 
				
			||||||
 | 
					type AuthenticatedMempoolDecorator struct {
 | 
				
			||||||
 | 
						addressFetchers []AddressFetcher
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewAuthenticatedMempoolDecorator(fetchers ...AddressFetcher) AuthenticatedMempoolDecorator {
 | 
				
			||||||
 | 
						return AuthenticatedMempoolDecorator{
 | 
				
			||||||
 | 
							addressFetchers: fetchers,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (amd AuthenticatedMempoolDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
 | 
				
			||||||
 | 
						// This is only for local mempool purposes, and thus is only run on check tx.
 | 
				
			||||||
 | 
						if ctx.IsCheckTx() && !simulate {
 | 
				
			||||||
 | 
							sigTx, ok := tx.(sigVerifiableTx)
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "tx must be sig verifiable tx")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !commonAddressesExist(sigTx.GetSigners(), amd.fetchAuthorizedAddresses(ctx)) {
 | 
				
			||||||
 | 
								return ctx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "tx contains no signers authorized for this mempool")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return next(ctx, tx, simulate)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (amd AuthenticatedMempoolDecorator) fetchAuthorizedAddresses(ctx sdk.Context) []sdk.AccAddress {
 | 
				
			||||||
 | 
						addrs := []sdk.AccAddress{}
 | 
				
			||||||
 | 
						for _, fetch := range amd.addressFetchers {
 | 
				
			||||||
 | 
							addrs = append(addrs, fetch(ctx)...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return addrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// commonAddressesExist checks if there is any intersection between two lists of addresses
 | 
				
			||||||
 | 
					func commonAddressesExist(addresses1, addresses2 []sdk.AccAddress) bool {
 | 
				
			||||||
 | 
						for _, a1 := range addresses1 {
 | 
				
			||||||
 | 
							for _, a2 := range addresses2 {
 | 
				
			||||||
 | 
								if a1.Equals(a2) {
 | 
				
			||||||
 | 
									return true
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										144
									
								
								app/ante/authorized_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								app/ante/authorized_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,144 @@
 | 
				
			|||||||
 | 
					package ante
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/rand"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/simapp/helpers"
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/x/bank"
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/require"
 | 
				
			||||||
 | 
						"github.com/tendermint/tendermint/crypto"
 | 
				
			||||||
 | 
						"github.com/tendermint/tendermint/crypto/secp256k1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/bep3"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						_ sdk.AnteHandler = (&MockAnteHandler{}).AnteHandle
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type MockAnteHandler struct {
 | 
				
			||||||
 | 
						WasCalled bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (mah *MockAnteHandler) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool) (sdk.Context, error) {
 | 
				
			||||||
 | 
						mah.WasCalled = true
 | 
				
			||||||
 | 
						return ctx, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func mockAddressFetcher(addresses ...sdk.AccAddress) AddressFetcher {
 | 
				
			||||||
 | 
						return func(sdk.Context) []sdk.AccAddress { return addresses }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAuthenticatedMempoolDecorator_AnteHandle_NotCheckTx(t *testing.T) {
 | 
				
			||||||
 | 
						testPrivKeys, testAddresses := generatePrivKeyAddressPairs(5)
 | 
				
			||||||
 | 
						fetcher := mockAddressFetcher(testAddresses[1:]...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						decorator := NewAuthenticatedMempoolDecorator(fetcher)
 | 
				
			||||||
 | 
						tx := helpers.GenTx(
 | 
				
			||||||
 | 
							[]sdk.Msg{
 | 
				
			||||||
 | 
								bep3.NewMsgClaimAtomicSwap(
 | 
				
			||||||
 | 
									testAddresses[0],
 | 
				
			||||||
 | 
									[]byte{},
 | 
				
			||||||
 | 
									[]byte{},
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							sdk.NewCoins(), // no fee
 | 
				
			||||||
 | 
							helpers.DefaultGenTxGas,
 | 
				
			||||||
 | 
							"testing-chain-id",
 | 
				
			||||||
 | 
							[]uint64{0},
 | 
				
			||||||
 | 
							[]uint64{0},
 | 
				
			||||||
 | 
							testPrivKeys[0], // address is not authorized
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						mmd := MockAnteHandler{}
 | 
				
			||||||
 | 
						ctx := sdk.Context{}.WithIsCheckTx(false) // run as it would be during block update ('DeliverTx'), not just checking entry to mempool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := decorator.AnteHandle(ctx, tx, false, mmd.AnteHandle)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						require.NoError(t, err)
 | 
				
			||||||
 | 
						require.True(t, mmd.WasCalled)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAuthenticatedMempoolDecorator_AnteHandle_Pass(t *testing.T) {
 | 
				
			||||||
 | 
						testPrivKeys, testAddresses := generatePrivKeyAddressPairs(5)
 | 
				
			||||||
 | 
						fetcher := mockAddressFetcher(testAddresses[1:]...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						decorator := NewAuthenticatedMempoolDecorator(fetcher)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tx := helpers.GenTx(
 | 
				
			||||||
 | 
							[]sdk.Msg{
 | 
				
			||||||
 | 
								bank.NewMsgSend(
 | 
				
			||||||
 | 
									testAddresses[0],
 | 
				
			||||||
 | 
									testAddresses[1],
 | 
				
			||||||
 | 
									sdk.NewCoins(sdk.NewInt64Coin("ukava", 100_000_000)),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								bep3.NewMsgClaimAtomicSwap(
 | 
				
			||||||
 | 
									testAddresses[2],
 | 
				
			||||||
 | 
									nil,
 | 
				
			||||||
 | 
									nil,
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							sdk.NewCoins(), // no fee
 | 
				
			||||||
 | 
							helpers.DefaultGenTxGas,
 | 
				
			||||||
 | 
							"testing-chain-id",
 | 
				
			||||||
 | 
							[]uint64{0, 123},
 | 
				
			||||||
 | 
							[]uint64{0, 123},
 | 
				
			||||||
 | 
							testPrivKeys[0], // not in list of authorized addresses
 | 
				
			||||||
 | 
							testPrivKeys[2],
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						mmd := MockAnteHandler{}
 | 
				
			||||||
 | 
						ctx := sdk.Context{}.WithIsCheckTx(true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := decorator.AnteHandle(ctx, tx, false, mmd.AnteHandle)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						require.NoError(t, err)
 | 
				
			||||||
 | 
						require.True(t, mmd.WasCalled)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAuthenticatedMempoolDecorator_AnteHandle_Reject(t *testing.T) {
 | 
				
			||||||
 | 
						testPrivKeys, testAddresses := generatePrivKeyAddressPairs(5)
 | 
				
			||||||
 | 
						fetcher := mockAddressFetcher(testAddresses[1:]...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						decorator := NewAuthenticatedMempoolDecorator(fetcher)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tx := helpers.GenTx(
 | 
				
			||||||
 | 
							[]sdk.Msg{
 | 
				
			||||||
 | 
								bank.NewMsgSend(
 | 
				
			||||||
 | 
									testAddresses[0],
 | 
				
			||||||
 | 
									testAddresses[1],
 | 
				
			||||||
 | 
									sdk.NewCoins(sdk.NewInt64Coin("ukava", 100_000_000)),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							sdk.NewCoins(), // no fee
 | 
				
			||||||
 | 
							helpers.DefaultGenTxGas,
 | 
				
			||||||
 | 
							"testing-chain-id",
 | 
				
			||||||
 | 
							[]uint64{0},
 | 
				
			||||||
 | 
							[]uint64{0},
 | 
				
			||||||
 | 
							testPrivKeys[0], // not in list of authorized addresses
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						mmd := MockAnteHandler{}
 | 
				
			||||||
 | 
						ctx := sdk.Context{}.WithIsCheckTx(true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := decorator.AnteHandle(ctx, tx, false, mmd.AnteHandle)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						require.Error(t, err)
 | 
				
			||||||
 | 
						require.False(t, mmd.WasCalled)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// generatePrivKeyAddressPairsFromRand generates (deterministically) a total of n private keys and addresses.
 | 
				
			||||||
 | 
					func generatePrivKeyAddressPairs(n int) (keys []crypto.PrivKey, addrs []sdk.AccAddress) {
 | 
				
			||||||
 | 
						r := rand.New(rand.NewSource(12345)) // make the generation deterministic
 | 
				
			||||||
 | 
						keys = make([]crypto.PrivKey, n)
 | 
				
			||||||
 | 
						addrs = make([]sdk.AccAddress, n)
 | 
				
			||||||
 | 
						for i := 0; i < n; i++ {
 | 
				
			||||||
 | 
							secret := make([]byte, 32)
 | 
				
			||||||
 | 
							_, err := r.Read(secret)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								panic("Could not read randomness")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							keys[i] = secp256k1.GenPrivKeySecp256k1(secret)
 | 
				
			||||||
 | 
							addrs[i] = sdk.AccAddress(keys[i].PubKey().Address())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								app/app.go
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								app/app.go
									
									
									
									
									
								
							@ -33,6 +33,7 @@ import (
 | 
				
			|||||||
	"github.com/cosmos/cosmos-sdk/x/upgrade"
 | 
						"github.com/cosmos/cosmos-sdk/x/upgrade"
 | 
				
			||||||
	upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client"
 | 
						upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/app/ante"
 | 
				
			||||||
	"github.com/kava-labs/kava/x/auction"
 | 
						"github.com/kava-labs/kava/x/auction"
 | 
				
			||||||
	"github.com/kava-labs/kava/x/bep3"
 | 
						"github.com/kava-labs/kava/x/bep3"
 | 
				
			||||||
	"github.com/kava-labs/kava/x/cdp"
 | 
						"github.com/kava-labs/kava/x/cdp"
 | 
				
			||||||
@ -116,6 +117,16 @@ var (
 | 
				
			|||||||
// Verify app interface at compile time
 | 
					// Verify app interface at compile time
 | 
				
			||||||
var _ simapp.App = (*App)(nil)
 | 
					var _ simapp.App = (*App)(nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AppOptions bundles several configuration params for an App.
 | 
				
			||||||
 | 
					// The zero value can be used as a sensible default.
 | 
				
			||||||
 | 
					type AppOptions struct {
 | 
				
			||||||
 | 
						SkipLoadLatest       bool
 | 
				
			||||||
 | 
						SkipUpgradeHeights   map[int64]bool
 | 
				
			||||||
 | 
						InvariantCheckPeriod uint
 | 
				
			||||||
 | 
						MempoolEnableAuth    bool
 | 
				
			||||||
 | 
						MempoolAuthAddresses []sdk.AccAddress
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// App represents an extended ABCI application
 | 
					// App represents an extended ABCI application
 | 
				
			||||||
type App struct {
 | 
					type App struct {
 | 
				
			||||||
	*bam.BaseApp
 | 
						*bam.BaseApp
 | 
				
			||||||
@ -159,9 +170,7 @@ type App struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewApp returns a reference to an initialized App.
 | 
					// NewApp returns a reference to an initialized App.
 | 
				
			||||||
func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
 | 
					func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts AppOptions, baseAppOptions ...func(*bam.BaseApp)) *App {
 | 
				
			||||||
	skipUpgradeHeights map[int64]bool, invCheckPeriod uint,
 | 
					 | 
				
			||||||
	baseAppOptions ...func(*bam.BaseApp)) *App {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cdc := MakeCodec()
 | 
						cdc := MakeCodec()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -182,7 +191,7 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
 | 
				
			|||||||
	var app = &App{
 | 
						var app = &App{
 | 
				
			||||||
		BaseApp:        bApp,
 | 
							BaseApp:        bApp,
 | 
				
			||||||
		cdc:            cdc,
 | 
							cdc:            cdc,
 | 
				
			||||||
		invCheckPeriod: invCheckPeriod,
 | 
							invCheckPeriod: appOpts.InvariantCheckPeriod,
 | 
				
			||||||
		keys:           keys,
 | 
							keys:           keys,
 | 
				
			||||||
		tkeys:          tkeys,
 | 
							tkeys:          tkeys,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -257,12 +266,12 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
	app.crisisKeeper = crisis.NewKeeper(
 | 
						app.crisisKeeper = crisis.NewKeeper(
 | 
				
			||||||
		crisisSubspace,
 | 
							crisisSubspace,
 | 
				
			||||||
		invCheckPeriod,
 | 
							app.invCheckPeriod,
 | 
				
			||||||
		app.supplyKeeper,
 | 
							app.supplyKeeper,
 | 
				
			||||||
		auth.FeeCollectorName,
 | 
							auth.FeeCollectorName,
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	app.upgradeKeeper = upgrade.NewKeeper(
 | 
						app.upgradeKeeper = upgrade.NewKeeper(
 | 
				
			||||||
		skipUpgradeHeights,
 | 
							appOpts.SkipUpgradeHeights,
 | 
				
			||||||
		keys[upgrade.StoreKey],
 | 
							keys[upgrade.StoreKey],
 | 
				
			||||||
		app.cdc,
 | 
							app.cdc,
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
@ -473,11 +482,18 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
 | 
				
			|||||||
	// initialize the app
 | 
						// initialize the app
 | 
				
			||||||
	app.SetInitChainer(app.InitChainer)
 | 
						app.SetInitChainer(app.InitChainer)
 | 
				
			||||||
	app.SetBeginBlocker(app.BeginBlocker)
 | 
						app.SetBeginBlocker(app.BeginBlocker)
 | 
				
			||||||
	app.SetAnteHandler(auth.NewAnteHandler(app.accountKeeper, app.supplyKeeper, auth.DefaultSigVerificationGasConsumer))
 | 
						var antehandler sdk.AnteHandler
 | 
				
			||||||
 | 
						if appOpts.MempoolEnableAuth {
 | 
				
			||||||
 | 
							var getAuthorizedAddresses ante.AddressFetcher = func(sdk.Context) []sdk.AccAddress { return appOpts.MempoolAuthAddresses }
 | 
				
			||||||
 | 
							antehandler = ante.NewAnteHandler(app.accountKeeper, app.supplyKeeper, auth.DefaultSigVerificationGasConsumer, app.bep3Keeper.GetAuthorizedAddresses, app.pricefeedKeeper.GetAuthorizedAddresses, getAuthorizedAddresses)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							antehandler = ante.NewAnteHandler(app.accountKeeper, app.supplyKeeper, auth.DefaultSigVerificationGasConsumer)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						app.SetAnteHandler(antehandler)
 | 
				
			||||||
	app.SetEndBlocker(app.EndBlocker)
 | 
						app.SetEndBlocker(app.EndBlocker)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// load store
 | 
						// load store
 | 
				
			||||||
	if loadLatest {
 | 
						if !appOpts.SkipLoadLatest {
 | 
				
			||||||
		err := app.LoadLatestVersion(app.keys[bam.MainStoreKey])
 | 
							err := app.LoadLatestVersion(app.keys[bam.MainStoreKey])
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			tmos.Exit(err.Error())
 | 
								tmos.Exit(err.Error())
 | 
				
			||||||
 | 
				
			|||||||
@ -16,11 +16,11 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestExport(t *testing.T) {
 | 
					func TestExport(t *testing.T) {
 | 
				
			||||||
	db := db.NewMemDB()
 | 
						db := db.NewMemDB()
 | 
				
			||||||
	app := NewApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, 0)
 | 
						app := NewApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, AppOptions{})
 | 
				
			||||||
	setGenesis(app)
 | 
						setGenesis(app)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 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
 | 
				
			||||||
	newApp := NewApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, 0)
 | 
						newApp := NewApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, AppOptions{})
 | 
				
			||||||
	_, _, err := newApp.ExportAppStateAndValidators(false, []string{})
 | 
						_, _, err := newApp.ExportAppStateAndValidators(false, []string{})
 | 
				
			||||||
	require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
 | 
						require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -28,7 +28,7 @@ func TestExport(t *testing.T) {
 | 
				
			|||||||
// ensure that black listed addresses are properly set in bank keeper
 | 
					// ensure that black listed addresses are properly set in bank keeper
 | 
				
			||||||
func TestBlackListedAddrs(t *testing.T) {
 | 
					func TestBlackListedAddrs(t *testing.T) {
 | 
				
			||||||
	db := db.NewMemDB()
 | 
						db := db.NewMemDB()
 | 
				
			||||||
	app := NewApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, 0)
 | 
						app := NewApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, AppOptions{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for acc := range mAccPerms {
 | 
						for acc := range mAccPerms {
 | 
				
			||||||
		require.Equal(t, !allowedReceivingModAcc[acc], app.bankKeeper.BlacklistedAddr(app.supplyKeeper.GetModuleAddress(acc)))
 | 
							require.Equal(t, !allowedReceivingModAcc[acc], app.bankKeeper.BlacklistedAddr(app.supplyKeeper.GetModuleAddress(acc)))
 | 
				
			||||||
 | 
				
			|||||||
@ -85,7 +85,7 @@ func TestFullAppSimulation(t *testing.T) {
 | 
				
			|||||||
		require.NoError(t, os.RemoveAll(dir))
 | 
							require.NoError(t, os.RemoveAll(dir))
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	app := NewApp(logger, db, nil, true, map[int64]bool{}, simapp.FlagPeriodValue, fauxMerkleModeOpt)
 | 
						app := NewApp(logger, db, nil, AppOptions{InvariantCheckPeriod: simapp.FlagPeriodValue}, fauxMerkleModeOpt)
 | 
				
			||||||
	require.Equal(t, appName, app.Name())
 | 
						require.Equal(t, appName, app.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// run randomized simulation
 | 
						// run randomized simulation
 | 
				
			||||||
@ -117,7 +117,7 @@ func TestAppImportExport(t *testing.T) {
 | 
				
			|||||||
		require.NoError(t, os.RemoveAll(dir))
 | 
							require.NoError(t, os.RemoveAll(dir))
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	app := NewApp(logger, db, nil, true, map[int64]bool{}, simapp.FlagPeriodValue, fauxMerkleModeOpt)
 | 
						app := NewApp(logger, db, nil, AppOptions{InvariantCheckPeriod: simapp.FlagPeriodValue}, fauxMerkleModeOpt)
 | 
				
			||||||
	require.Equal(t, appName, app.Name())
 | 
						require.Equal(t, appName, app.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Run randomized simulation
 | 
						// Run randomized simulation
 | 
				
			||||||
@ -151,7 +151,7 @@ func TestAppImportExport(t *testing.T) {
 | 
				
			|||||||
		require.NoError(t, os.RemoveAll(newDir))
 | 
							require.NoError(t, os.RemoveAll(newDir))
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	newApp := NewApp(log.NewNopLogger(), newDB, nil, true, map[int64]bool{}, simapp.FlagPeriodValue, fauxMerkleModeOpt)
 | 
						newApp := NewApp(log.NewNopLogger(), newDB, nil, AppOptions{InvariantCheckPeriod: simapp.FlagPeriodValue}, fauxMerkleModeOpt)
 | 
				
			||||||
	require.Equal(t, appName, newApp.Name())
 | 
						require.Equal(t, appName, newApp.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var genesisState GenesisState
 | 
						var genesisState GenesisState
 | 
				
			||||||
@ -212,7 +212,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
 | 
				
			|||||||
		require.NoError(t, os.RemoveAll(dir))
 | 
							require.NoError(t, os.RemoveAll(dir))
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	app := NewApp(logger, db, nil, true, map[int64]bool{}, simapp.FlagPeriodValue, fauxMerkleModeOpt)
 | 
						app := NewApp(logger, db, nil, AppOptions{InvariantCheckPeriod: simapp.FlagPeriodValue}, fauxMerkleModeOpt)
 | 
				
			||||||
	require.Equal(t, appName, app.Name())
 | 
						require.Equal(t, appName, app.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Run randomized simulation
 | 
						// Run randomized simulation
 | 
				
			||||||
@ -251,7 +251,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
 | 
				
			|||||||
		require.NoError(t, os.RemoveAll(newDir))
 | 
							require.NoError(t, os.RemoveAll(newDir))
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	newApp := NewApp(log.NewNopLogger(), newDB, nil, true, map[int64]bool{}, simapp.FlagPeriodValue, fauxMerkleModeOpt)
 | 
						newApp := NewApp(log.NewNopLogger(), newDB, nil, AppOptions{InvariantCheckPeriod: simapp.FlagPeriodValue}, fauxMerkleModeOpt)
 | 
				
			||||||
	require.Equal(t, appName, newApp.Name())
 | 
						require.Equal(t, appName, newApp.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	newApp.InitChain(abci.RequestInitChain{
 | 
						newApp.InitChain(abci.RequestInitChain{
 | 
				
			||||||
@ -284,7 +284,7 @@ func TestAppStateDeterminism(t *testing.T) {
 | 
				
			|||||||
	for j := 0; j < numTimesToRunPerSeed; j++ {
 | 
						for j := 0; j < numTimesToRunPerSeed; j++ {
 | 
				
			||||||
		logger := log.NewNopLogger()
 | 
							logger := log.NewNopLogger()
 | 
				
			||||||
		db := dbm.NewMemDB()
 | 
							db := dbm.NewMemDB()
 | 
				
			||||||
		app := NewApp(logger, db, nil, true, map[int64]bool{}, simapp.FlagPeriodValue, interBlockCacheOpt())
 | 
							app := NewApp(logger, db, nil, AppOptions{InvariantCheckPeriod: simapp.FlagPeriodValue}, interBlockCacheOpt())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fmt.Printf(
 | 
							fmt.Printf(
 | 
				
			||||||
			"running non-determinism simulation; seed %d: attempt: %d/%d\n",
 | 
								"running non-determinism simulation; seed %d: attempt: %d/%d\n",
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,6 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	abci "github.com/tendermint/tendermint/abci/types"
 | 
						abci "github.com/tendermint/tendermint/abci/types"
 | 
				
			||||||
	"github.com/tendermint/tendermint/crypto"
 | 
						"github.com/tendermint/tendermint/crypto"
 | 
				
			||||||
	"github.com/tendermint/tendermint/crypto/ed25519"
 | 
					 | 
				
			||||||
	"github.com/tendermint/tendermint/crypto/secp256k1"
 | 
						"github.com/tendermint/tendermint/crypto/secp256k1"
 | 
				
			||||||
	"github.com/tendermint/tendermint/libs/log"
 | 
						"github.com/tendermint/tendermint/libs/log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -62,7 +61,7 @@ func NewTestApp() TestApp {
 | 
				
			|||||||
	SetBip44CoinType(config)
 | 
						SetBip44CoinType(config)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	db := tmdb.NewMemDB()
 | 
						db := tmdb.NewMemDB()
 | 
				
			||||||
	app := NewApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, 0)
 | 
						app := NewApp(log.NewNopLogger(), db, nil, AppOptions{})
 | 
				
			||||||
	return TestApp{App: *app}
 | 
						return TestApp{App: *app}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -188,8 +187,7 @@ func NewAuthGenState(addresses []sdk.AccAddress, coins []sdk.Coins) GenesisState
 | 
				
			|||||||
	return GenesisState{auth.ModuleName: auth.ModuleCdc.MustMarshalJSON(authGenesis)}
 | 
						return GenesisState{auth.ModuleName: auth.ModuleCdc.MustMarshalJSON(authGenesis)}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GeneratePrivKeyAddressPairsFromRand generates (deterministically) a total of n private keys and addresses.
 | 
					// GeneratePrivKeyAddressPairsFromRand generates (deterministically) a total of n secp256k1 private keys and addresses.
 | 
				
			||||||
// TODO only generate secp256 keys?
 | 
					 | 
				
			||||||
func GeneratePrivKeyAddressPairs(n int) (keys []crypto.PrivKey, addrs []sdk.AccAddress) {
 | 
					func GeneratePrivKeyAddressPairs(n int) (keys []crypto.PrivKey, addrs []sdk.AccAddress) {
 | 
				
			||||||
	r := rand.New(rand.NewSource(12345)) // make the generation deterministic
 | 
						r := rand.New(rand.NewSource(12345)) // make the generation deterministic
 | 
				
			||||||
	keys = make([]crypto.PrivKey, n)
 | 
						keys = make([]crypto.PrivKey, n)
 | 
				
			||||||
@ -200,11 +198,7 @@ func GeneratePrivKeyAddressPairs(n int) (keys []crypto.PrivKey, addrs []sdk.AccA
 | 
				
			|||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			panic("Could not read randomness")
 | 
								panic("Could not read randomness")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if r.Int63()%2 == 0 {
 | 
							keys[i] = secp256k1.GenPrivKeySecp256k1(secret)
 | 
				
			||||||
			keys[i] = secp256k1.GenPrivKeySecp256k1(secret)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			keys[i] = ed25519.GenPrivKeyFromSecret(secret)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		addrs[i] = sdk.AccAddress(keys[i].PubKey().Address())
 | 
							addrs[i] = sdk.AccAddress(keys[i].PubKey().Address())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										17
									
								
								app/utils.go
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								app/utils.go
									
									
									
									
									
								
							@ -1,17 +0,0 @@
 | 
				
			|||||||
package app
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"io/ioutil"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ExportStateToJSON util function to export the app state to JSON
 | 
					 | 
				
			||||||
func ExportStateToJSON(app *App, path string) error {
 | 
					 | 
				
			||||||
	fmt.Println("exporting app state...")
 | 
					 | 
				
			||||||
	appState, _, err := app.ExportAppStateAndValidators(false, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ioutil.WriteFile(path, []byte(appState), 0644)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -2,6 +2,7 @@ package main
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/spf13/cobra"
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
@ -28,7 +29,11 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// kvd custom flags
 | 
					// kvd custom flags
 | 
				
			||||||
const flagInvCheckPeriod = "inv-check-period"
 | 
					const (
 | 
				
			||||||
 | 
						flagInvCheckPeriod       = "inv-check-period"
 | 
				
			||||||
 | 
						flagMempoolEnableAuth    = "mempool.enable-authentication"
 | 
				
			||||||
 | 
						flagMempoolAuthAddresses = "mempool.authorized-addresses"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var invCheckPeriod uint
 | 
					var invCheckPeriod uint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -72,7 +77,23 @@ func main() {
 | 
				
			|||||||
	executor := cli.PrepareBaseCmd(rootCmd, "KA", app.DefaultNodeHome)
 | 
						executor := cli.PrepareBaseCmd(rootCmd, "KA", app.DefaultNodeHome)
 | 
				
			||||||
	rootCmd.PersistentFlags().UintVar(&invCheckPeriod, flagInvCheckPeriod,
 | 
						rootCmd.PersistentFlags().UintVar(&invCheckPeriod, flagInvCheckPeriod,
 | 
				
			||||||
		0, "Assert registered invariants every N blocks")
 | 
							0, "Assert registered invariants every N blocks")
 | 
				
			||||||
	err := executor.Execute()
 | 
						startCmd, _, err := rootCmd.Find([]string{"start"})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(fmt.Sprintf("could not find 'start' command on root command: %s", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						startCmd.Flags().Bool(flagMempoolEnableAuth, false, "Configure the mempool to only accept transactions from authorized addresses")
 | 
				
			||||||
 | 
						err = viper.BindPFlag(flagMempoolEnableAuth, startCmd.Flags().Lookup(flagMempoolEnableAuth))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(fmt.Sprintf("failed to bind flag: %s", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						startCmd.Flags().StringSlice(flagMempoolAuthAddresses, []string{}, "Additional addresses to accept transactions from when the mempool is running in authorized mode (comma separated kava addresses)")
 | 
				
			||||||
 | 
						err = viper.BindPFlag(flagMempoolAuthAddresses, startCmd.Flags().Lookup(flagMempoolAuthAddresses))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(fmt.Sprintf("failed to bind flag: %s", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// run main command
 | 
				
			||||||
 | 
						err = executor.Execute()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		panic(err)
 | 
							panic(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -95,8 +116,21 @@ func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer) abci.Application
 | 
				
			|||||||
		panic(err)
 | 
							panic(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mempoolEnableAuth := viper.GetBool(flagMempoolEnableAuth)
 | 
				
			||||||
 | 
						mempoolAuthAddresses, err := accAddressesFromBech32(viper.GetStringSlice(flagMempoolAuthAddresses)...)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(fmt.Sprintf("could not get authorized address from config: %v", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return app.NewApp(
 | 
						return app.NewApp(
 | 
				
			||||||
		logger, db, traceStore, true, skipUpgradeHeights, invCheckPeriod,
 | 
							logger, db, traceStore,
 | 
				
			||||||
 | 
							app.AppOptions{
 | 
				
			||||||
 | 
								SkipLoadLatest:       false,
 | 
				
			||||||
 | 
								SkipUpgradeHeights:   skipUpgradeHeights,
 | 
				
			||||||
 | 
								InvariantCheckPeriod: invCheckPeriod,
 | 
				
			||||||
 | 
								MempoolEnableAuth:    mempoolEnableAuth,
 | 
				
			||||||
 | 
								MempoolAuthAddresses: mempoolAuthAddresses,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		baseapp.SetPruning(pruningOpts),
 | 
							baseapp.SetPruning(pruningOpts),
 | 
				
			||||||
		baseapp.SetMinGasPrices(viper.GetString(server.FlagMinGasPrices)),
 | 
							baseapp.SetMinGasPrices(viper.GetString(server.FlagMinGasPrices)),
 | 
				
			||||||
		baseapp.SetHaltHeight(viper.GetUint64(server.FlagHaltHeight)),
 | 
							baseapp.SetHaltHeight(viper.GetUint64(server.FlagHaltHeight)),
 | 
				
			||||||
@ -110,13 +144,33 @@ func exportAppStateAndTMValidators(
 | 
				
			|||||||
) (json.RawMessage, []tmtypes.GenesisValidator, error) {
 | 
					) (json.RawMessage, []tmtypes.GenesisValidator, error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if height != -1 {
 | 
						if height != -1 {
 | 
				
			||||||
		tempApp := app.NewApp(logger, db, traceStore, false, map[int64]bool{}, uint(1))
 | 
							opts := app.AppOptions{
 | 
				
			||||||
 | 
								SkipLoadLatest:       true,
 | 
				
			||||||
 | 
								InvariantCheckPeriod: uint(1),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							tempApp := app.NewApp(logger, db, traceStore, opts)
 | 
				
			||||||
		err := tempApp.LoadHeight(height)
 | 
							err := tempApp.LoadHeight(height)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, nil, err
 | 
								return nil, nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return tempApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
 | 
							return tempApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	tempApp := app.NewApp(logger, db, traceStore, true, map[int64]bool{}, uint(1))
 | 
						opts := app.AppOptions{
 | 
				
			||||||
 | 
							SkipLoadLatest:       false,
 | 
				
			||||||
 | 
							InvariantCheckPeriod: uint(1),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						tempApp := app.NewApp(logger, db, traceStore, opts)
 | 
				
			||||||
	return tempApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
 | 
						return tempApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func accAddressesFromBech32(addresses ...string) ([]sdk.AccAddress, error) {
 | 
				
			||||||
 | 
						var decodedAddresses []sdk.AccAddress
 | 
				
			||||||
 | 
						for _, s := range addresses {
 | 
				
			||||||
 | 
							a, err := sdk.AccAddressFromBech32(s)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							decodedAddresses = append(decodedAddresses, a)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return decodedAddresses, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.mod
									
									
									
									
									
								
							@ -3,12 +3,12 @@ module github.com/kava-labs/kava
 | 
				
			|||||||
go 1.13
 | 
					go 1.13
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/cosmos/cosmos-sdk v0.39.1
 | 
						github.com/cosmos/cosmos-sdk v0.39.2
 | 
				
			||||||
	github.com/gorilla/mux v1.7.4
 | 
						github.com/gorilla/mux v1.7.4
 | 
				
			||||||
	github.com/spf13/cobra v1.0.0
 | 
						github.com/spf13/cobra v1.0.0
 | 
				
			||||||
	github.com/spf13/viper v1.6.3
 | 
						github.com/spf13/viper v1.6.3
 | 
				
			||||||
	github.com/stretchr/testify v1.6.1
 | 
						github.com/stretchr/testify v1.6.1
 | 
				
			||||||
	github.com/tendermint/tendermint v0.33.7
 | 
						github.com/tendermint/tendermint v0.33.9
 | 
				
			||||||
	github.com/tendermint/tm-db v0.5.1
 | 
						github.com/tendermint/tm-db v0.5.1
 | 
				
			||||||
	gopkg.in/yaml.v2 v2.3.0
 | 
						gopkg.in/yaml.v2 v2.3.0
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										46
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								go.sum
									
									
									
									
									
								
							@ -1,7 +1,7 @@
 | 
				
			|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 | 
					cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 | 
				
			||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 | 
					cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 | 
				
			||||||
github.com/99designs/keyring v1.1.3 h1:mEV3iyZWjkxQ7R8ia8GcG97vCX5zQQ7n4o8R2BylwQY=
 | 
					github.com/99designs/keyring v1.1.6 h1:kVDC2uCgVwecxCk+9zoCt2uEL6dt+dfVzMvGgnVcIuM=
 | 
				
			||||||
github.com/99designs/keyring v1.1.3/go.mod h1:657DQuMrBZRtuL/voxVyiyb6zpMehlm5vLB9Qwrv904=
 | 
					github.com/99designs/keyring v1.1.6/go.mod h1:16e0ds7LGQQcT59QqkTg72Hh5ShM51Byv5PEmW6uoRU=
 | 
				
			||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 | 
					github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 | 
				
			||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 | 
					github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 | 
				
			||||||
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg=
 | 
					github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg=
 | 
				
			||||||
@ -68,8 +68,8 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7
 | 
				
			|||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 | 
					github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 | 
				
			||||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
 | 
					github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
 | 
				
			||||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
 | 
					github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
 | 
				
			||||||
github.com/cosmos/cosmos-sdk v0.39.1 h1:vhjf9PZh9ph8btAj9aBpHoVITgVVjNBpM3x5Gl/Vwac=
 | 
					github.com/cosmos/cosmos-sdk v0.39.2 h1:nLfCJMkUuFt7ansi/YvCxwwxLFrgHCA3cYP4sJKYQdk=
 | 
				
			||||||
github.com/cosmos/cosmos-sdk v0.39.1/go.mod h1:ry2ROl5n+f2/QXpKJo3rdWNJwll00z7KhIVcxNcl16M=
 | 
					github.com/cosmos/cosmos-sdk v0.39.2/go.mod h1:VNUluciWBFj2vkhpMcp8rYZL/kCw0FtNc7SseUjE1KM=
 | 
				
			||||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d h1:49RLWk1j44Xu4fjHb6JFYmeUnDORVwHNkDxaQ0ctCVU=
 | 
					github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d h1:49RLWk1j44Xu4fjHb6JFYmeUnDORVwHNkDxaQ0ctCVU=
 | 
				
			||||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
 | 
					github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
 | 
				
			||||||
github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4=
 | 
					github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4=
 | 
				
			||||||
@ -88,8 +88,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 | 
				
			|||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 | 
					github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 | 
				
			||||||
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/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 | 
					github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 | 
				
			||||||
github.com/dvsekhvalnov/jose2go v0.0.0-20180829124132-7f401d37b68a h1:mq+R6XEM6lJX5VlLyZIrUSP8tSuJp82xTK89hvBwJbU=
 | 
					github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b h1:HBah4D48ypg3J7Np4N+HY/ZR76fx3HEUGxDU6Uk39oQ=
 | 
				
			||||||
github.com/dvsekhvalnov/jose2go v0.0.0-20180829124132-7f401d37b68a/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM=
 | 
					github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM=
 | 
				
			||||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
 | 
					github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
 | 
				
			||||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
 | 
					github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
 | 
				
			||||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
 | 
					github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
 | 
				
			||||||
@ -150,9 +150,13 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
 | 
				
			|||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
 | 
					github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
 | 
				
			||||||
github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
 | 
					github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
 | 
				
			||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
 | 
					github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
 | 
				
			||||||
 | 
					github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0=
 | 
				
			||||||
 | 
					github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
 | 
				
			||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
					github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
				
			||||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
 | 
					github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
 | 
				
			||||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
					github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
				
			||||||
 | 
					github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
 | 
				
			||||||
 | 
					github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
				
			||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 | 
					github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 | 
				
			||||||
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
 | 
					github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
 | 
				
			||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 | 
					github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 | 
				
			||||||
@ -160,6 +164,8 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
 | 
				
			|||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 | 
					github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 | 
				
			||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 | 
					github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 | 
				
			||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
					github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
				
			||||||
 | 
					github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
 | 
				
			||||||
 | 
					github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
				
			||||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
 | 
					github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
 | 
				
			||||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
 | 
					github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
 | 
				
			||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 | 
					github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 | 
				
			||||||
@ -285,6 +291,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
 | 
				
			|||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
					github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
				
			||||||
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/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 | 
					github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 | 
				
			||||||
 | 
					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/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/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
 | 
					github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
 | 
				
			||||||
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
 | 
					github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
 | 
				
			||||||
@ -426,11 +434,11 @@ github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM
 | 
				
			|||||||
github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso=
 | 
					github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso=
 | 
				
			||||||
github.com/tendermint/go-amino v0.15.1 h1:D2uk35eT4iTsvJd9jWIetzthE5C0/k2QmMFkCN+4JgQ=
 | 
					github.com/tendermint/go-amino v0.15.1 h1:D2uk35eT4iTsvJd9jWIetzthE5C0/k2QmMFkCN+4JgQ=
 | 
				
			||||||
github.com/tendermint/go-amino v0.15.1/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
 | 
					github.com/tendermint/go-amino v0.15.1/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
 | 
				
			||||||
github.com/tendermint/iavl v0.14.0 h1:Jkff+IFrXxRWtH9Jn/ga/2cxNnzMTv58xEKgCJsKUBg=
 | 
					github.com/tendermint/iavl v0.14.1 h1:jz7YOvGiPwmcqqVMcSMjxCu4WXtQYGhKdKrWTTJ5EKs=
 | 
				
			||||||
github.com/tendermint/iavl v0.14.0/go.mod h1:QmfViflFiXzxKLQE4tAUuWQHq+RSuQFxablW5oJZ6sE=
 | 
					github.com/tendermint/iavl v0.14.1/go.mod h1:QmfViflFiXzxKLQE4tAUuWQHq+RSuQFxablW5oJZ6sE=
 | 
				
			||||||
github.com/tendermint/tendermint v0.33.5/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM=
 | 
					github.com/tendermint/tendermint v0.33.5/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM=
 | 
				
			||||||
github.com/tendermint/tendermint v0.33.7 h1:b5CQD8ggDtl4u0EbXzabi0MaOw9NrcXker6ijEkAE74=
 | 
					github.com/tendermint/tendermint v0.33.9 h1:rRKIfu5qAXX5f9bwX1oUXSZz/ALFJjDuivhkbGUQxiU=
 | 
				
			||||||
github.com/tendermint/tendermint v0.33.7/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM=
 | 
					github.com/tendermint/tendermint v0.33.9/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM=
 | 
				
			||||||
github.com/tendermint/tm-db v0.5.1 h1:H9HDq8UEA7Eeg13kdYckkgwwkQLBnJGgX4PgLJRhieY=
 | 
					github.com/tendermint/tm-db v0.5.1 h1:H9HDq8UEA7Eeg13kdYckkgwwkQLBnJGgX4PgLJRhieY=
 | 
				
			||||||
github.com/tendermint/tm-db v0.5.1/go.mod h1:g92zWjHpCYlEvQXvy9M168Su8V1IBEeawpXVVBaK4f4=
 | 
					github.com/tendermint/tm-db v0.5.1/go.mod h1:g92zWjHpCYlEvQXvy9M168Su8V1IBEeawpXVVBaK4f4=
 | 
				
			||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 | 
					github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 | 
				
			||||||
@ -470,6 +478,8 @@ golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 h1:DOmugCavvUtnUD114C1Wh+
 | 
				
			|||||||
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
					golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
				
			||||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88=
 | 
					golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88=
 | 
				
			||||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
					golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
				
			||||||
 | 
					golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
 | 
				
			||||||
 | 
					golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
				
			||||||
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=
 | 
				
			||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 | 
					golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 | 
				
			||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 | 
					golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 | 
				
			||||||
@ -499,6 +509,8 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH
 | 
				
			|||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
					golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
				
			||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
 | 
					golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
 | 
				
			||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 | 
					golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 | 
				
			||||||
 | 
					golang.org/x/net v0.0.0-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY=
 | 
				
			||||||
 | 
					golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 | 
				
			||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
					golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
				
			||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
					golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
@ -529,9 +541,14 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgm
 | 
				
			|||||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
 | 
					golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb h1:HS9IzC4UFbpMBLQUDSQcU+ViVT1vdFCQVjdPVpTlZrs=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
					golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
				
			||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 | 
					golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 | 
				
			||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 | 
					golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 | 
				
			||||||
 | 
					golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
 | 
				
			||||||
 | 
					golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
				
			||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
					golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
				
			||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
					golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
				
			||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
					golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
				
			||||||
@ -565,6 +582,8 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRn
 | 
				
			|||||||
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
 | 
					google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
 | 
				
			||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
 | 
					google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
 | 
				
			||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 | 
					google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 | 
				
			||||||
 | 
					google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
 | 
				
			||||||
 | 
					google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
 | 
				
			||||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
 | 
					google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
 | 
				
			||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 | 
					google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 | 
				
			||||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
 | 
					google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
 | 
				
			||||||
@ -575,18 +594,21 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
 | 
				
			|||||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 | 
					google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 | 
				
			||||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
 | 
					google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
 | 
				
			||||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 | 
					google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 | 
				
			||||||
 | 
					google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 | 
				
			||||||
google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4=
 | 
					google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4=
 | 
				
			||||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
 | 
					google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
 | 
				
			||||||
google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k=
 | 
					google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k=
 | 
				
			||||||
google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
 | 
					google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
 | 
				
			||||||
google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE=
 | 
					 | 
				
			||||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
 | 
					 | 
				
			||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 | 
					google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 | 
				
			||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 | 
					google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 | 
				
			||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
 | 
					google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
 | 
				
			||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
 | 
					google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
 | 
				
			||||||
google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw=
 | 
					google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw=
 | 
				
			||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
 | 
					google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
 | 
				
			||||||
 | 
					google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 | 
				
			||||||
 | 
					google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 | 
				
			||||||
 | 
					google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
 | 
				
			||||||
 | 
					google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 | 
				
			||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 | 
					gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 | 
				
			||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
					gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
				
			||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
					gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
				
			||||||
 | 
				
			|||||||
@ -139,3 +139,28 @@ func (k Keeper) GetSupplyLimit(ctx sdk.Context, denom string) (types.SupplyLimit
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return asset.SupplyLimit, nil
 | 
						return asset.SupplyLimit, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ------------------------------------------
 | 
				
			||||||
 | 
					//				Cross Asset Getters
 | 
				
			||||||
 | 
					// ------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetAuthorizedAddresses returns a list of addresses that have special authorization within this module, eg all the deputies.
 | 
				
			||||||
 | 
					func (k Keeper) GetAuthorizedAddresses(ctx sdk.Context) []sdk.AccAddress {
 | 
				
			||||||
 | 
						assetParams, found := k.GetAssets(ctx)
 | 
				
			||||||
 | 
						if !found {
 | 
				
			||||||
 | 
							// no assets params is a valid genesis state
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						addresses := []sdk.AccAddress{}
 | 
				
			||||||
 | 
						uniqueAddresses := map[string]bool{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, ap := range assetParams {
 | 
				
			||||||
 | 
							a := ap.DeputyAddress
 | 
				
			||||||
 | 
							// de-dup addresses
 | 
				
			||||||
 | 
							if _, found := uniqueAddresses[a.String()]; !found {
 | 
				
			||||||
 | 
								addresses = append(addresses, a)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							uniqueAddresses[a.String()] = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return addresses
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -116,6 +116,14 @@ func (suite *ParamsTestSuite) TestGetAssetByCoinID() {
 | 
				
			|||||||
	suite.Equal(asset, res)
 | 
						suite.Equal(asset, res)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ParamsTestSuite) TestGetAuthorizedAddresses() {
 | 
				
			||||||
 | 
						deputyAddresses := suite.keeper.GetAuthorizedAddresses(suite.ctx)
 | 
				
			||||||
 | 
						// the test params use the same deputy address for two assets
 | 
				
			||||||
 | 
						expectedAddresses := []sdk.AccAddress{suite.addrs[0]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						suite.Require().ElementsMatch(expectedAddresses, deputyAddresses)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *AssetTestSuite) TestValidateLiveAsset() {
 | 
					func (suite *AssetTestSuite) TestValidateLiveAsset() {
 | 
				
			||||||
	type args struct {
 | 
						type args struct {
 | 
				
			||||||
		coin sdk.Coin
 | 
							coin sdk.Coin
 | 
				
			||||||
 | 
				
			|||||||
@ -59,3 +59,20 @@ func (k Keeper) GetMarket(ctx sdk.Context, marketID string) (types.Market, bool)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return types.Market{}, false
 | 
						return types.Market{}, false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetAuthorizedAddresses returns a list of addresses that have special authorization within this module, eg the oracles of all markets.
 | 
				
			||||||
 | 
					func (k Keeper) GetAuthorizedAddresses(ctx sdk.Context) []sdk.AccAddress {
 | 
				
			||||||
 | 
						oracles := []sdk.AccAddress{}
 | 
				
			||||||
 | 
						uniqueOracles := map[string]bool{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, m := range k.GetMarkets(ctx) {
 | 
				
			||||||
 | 
							for _, o := range m.Oracles {
 | 
				
			||||||
 | 
								// de-dup list of oracles
 | 
				
			||||||
 | 
								if _, found := uniqueOracles[o.String()]; !found {
 | 
				
			||||||
 | 
									oracles = append(oracles, o)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								uniqueOracles[o.String()] = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return oracles
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,7 @@ import (
 | 
				
			|||||||
	tmtime "github.com/tendermint/tendermint/types/time"
 | 
						tmtime "github.com/tendermint/tendermint/types/time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/kava-labs/kava/app"
 | 
						"github.com/kava-labs/kava/app"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/pricefeed"
 | 
				
			||||||
	"github.com/kava-labs/kava/x/pricefeed/keeper"
 | 
						"github.com/kava-labs/kava/x/pricefeed/keeper"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -38,15 +39,32 @@ func (suite *KeeperTestSuite) SetupTest() {
 | 
				
			|||||||
func (suite *KeeperTestSuite) TestGetSetOracles() {
 | 
					func (suite *KeeperTestSuite) TestGetSetOracles() {
 | 
				
			||||||
	params := suite.keeper.GetParams(suite.ctx)
 | 
						params := suite.keeper.GetParams(suite.ctx)
 | 
				
			||||||
	suite.Equal([]sdk.AccAddress(nil), params.Markets[0].Oracles)
 | 
						suite.Equal([]sdk.AccAddress(nil), params.Markets[0].Oracles)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	params.Markets[0].Oracles = suite.addrs
 | 
						params.Markets[0].Oracles = suite.addrs
 | 
				
			||||||
	suite.NotPanics(func() { suite.keeper.SetParams(suite.ctx, params) })
 | 
						suite.NotPanics(func() { suite.keeper.SetParams(suite.ctx, params) })
 | 
				
			||||||
	params = suite.keeper.GetParams(suite.ctx)
 | 
						params = suite.keeper.GetParams(suite.ctx)
 | 
				
			||||||
	suite.Equal(suite.addrs, params.Markets[0].Oracles)
 | 
						suite.Equal(suite.addrs, params.Markets[0].Oracles)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	addr, err := suite.keeper.GetOracle(suite.ctx, params.Markets[0].MarketID, suite.addrs[0])
 | 
						addr, err := suite.keeper.GetOracle(suite.ctx, params.Markets[0].MarketID, suite.addrs[0])
 | 
				
			||||||
	suite.NoError(err)
 | 
						suite.NoError(err)
 | 
				
			||||||
	suite.Equal(suite.addrs[0], addr)
 | 
						suite.Equal(suite.addrs[0], addr)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *KeeperTestSuite) TestGetAuthorizedAddresses() {
 | 
				
			||||||
 | 
						_, oracles := app.GeneratePrivKeyAddressPairs(5)
 | 
				
			||||||
 | 
						params := pricefeed.Params{
 | 
				
			||||||
 | 
							Markets: []pricefeed.Market{
 | 
				
			||||||
 | 
								{MarketID: "btc:usd", BaseAsset: "btc", QuoteAsset: "usd", Oracles: oracles[:3], Active: true},
 | 
				
			||||||
 | 
								{MarketID: "xrp:usd", BaseAsset: "xrp", QuoteAsset: "usd", Oracles: oracles[2:], Active: true},
 | 
				
			||||||
 | 
								{MarketID: "xrp:usd:30", BaseAsset: "xrp", QuoteAsset: "usd", Oracles: nil, Active: true},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						suite.keeper.SetParams(suite.ctx, params)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						actualOracles := suite.keeper.GetAuthorizedAddresses(suite.ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						suite.Require().ElementsMatch(oracles, actualOracles)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
func TestKeeperTestSuite(t *testing.T) {
 | 
					func TestKeeperTestSuite(t *testing.T) {
 | 
				
			||||||
	suite.Run(t, new(KeeperTestSuite))
 | 
						suite.Run(t, new(KeeperTestSuite))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user