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:
Ruaridh 2020-12-02 17:37:11 +00:00 committed by GitHub
parent 9472c09b91
commit 9c69ee2fbf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 640 additions and 62 deletions

32
app/ante/ante.go Normal file
View 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
View 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
View 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
View 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
}

View File

@ -33,6 +33,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/upgrade"
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/bep3"
"github.com/kava-labs/kava/x/cdp"
@ -116,6 +117,16 @@ var (
// Verify app interface at compile time
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
type App struct {
*bam.BaseApp
@ -159,9 +170,7 @@ type App struct {
}
// NewApp returns a reference to an initialized App.
func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
skipUpgradeHeights map[int64]bool, invCheckPeriod uint,
baseAppOptions ...func(*bam.BaseApp)) *App {
func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts AppOptions, baseAppOptions ...func(*bam.BaseApp)) *App {
cdc := MakeCodec()
@ -182,7 +191,7 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
var app = &App{
BaseApp: bApp,
cdc: cdc,
invCheckPeriod: invCheckPeriod,
invCheckPeriod: appOpts.InvariantCheckPeriod,
keys: keys,
tkeys: tkeys,
}
@ -257,12 +266,12 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
)
app.crisisKeeper = crisis.NewKeeper(
crisisSubspace,
invCheckPeriod,
app.invCheckPeriod,
app.supplyKeeper,
auth.FeeCollectorName,
)
app.upgradeKeeper = upgrade.NewKeeper(
skipUpgradeHeights,
appOpts.SkipUpgradeHeights,
keys[upgrade.StoreKey],
app.cdc,
)
@ -473,11 +482,18 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
// initialize the app
app.SetInitChainer(app.InitChainer)
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)
// load store
if loadLatest {
if !appOpts.SkipLoadLatest {
err := app.LoadLatestVersion(app.keys[bam.MainStoreKey])
if err != nil {
tmos.Exit(err.Error())

View File

@ -16,11 +16,11 @@ import (
func TestExport(t *testing.T) {
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)
// 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{})
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
func TestBlackListedAddrs(t *testing.T) {
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 {
require.Equal(t, !allowedReceivingModAcc[acc], app.bankKeeper.BlacklistedAddr(app.supplyKeeper.GetModuleAddress(acc)))

View File

@ -85,7 +85,7 @@ func TestFullAppSimulation(t *testing.T) {
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())
// run randomized simulation
@ -117,7 +117,7 @@ func TestAppImportExport(t *testing.T) {
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())
// Run randomized simulation
@ -151,7 +151,7 @@ func TestAppImportExport(t *testing.T) {
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())
var genesisState GenesisState
@ -212,7 +212,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
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())
// Run randomized simulation
@ -251,7 +251,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
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())
newApp.InitChain(abci.RequestInitChain{
@ -284,7 +284,7 @@ func TestAppStateDeterminism(t *testing.T) {
for j := 0; j < numTimesToRunPerSeed; j++ {
logger := log.NewNopLogger()
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(
"running non-determinism simulation; seed %d: attempt: %d/%d\n",

View File

@ -11,7 +11,6 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/secp256k1"
"github.com/tendermint/tendermint/libs/log"
@ -62,7 +61,7 @@ func NewTestApp() TestApp {
SetBip44CoinType(config)
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}
}
@ -188,8 +187,7 @@ func NewAuthGenState(addresses []sdk.AccAddress, coins []sdk.Coins) GenesisState
return GenesisState{auth.ModuleName: auth.ModuleCdc.MustMarshalJSON(authGenesis)}
}
// GeneratePrivKeyAddressPairsFromRand generates (deterministically) a total of n private keys and addresses.
// TODO only generate secp256 keys?
// GeneratePrivKeyAddressPairsFromRand generates (deterministically) a total of n secp256k1 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)
@ -200,11 +198,7 @@ func GeneratePrivKeyAddressPairs(n int) (keys []crypto.PrivKey, addrs []sdk.AccA
if err != nil {
panic("Could not read randomness")
}
if r.Int63()%2 == 0 {
keys[i] = secp256k1.GenPrivKeySecp256k1(secret)
} else {
keys[i] = ed25519.GenPrivKeyFromSecret(secret)
}
addrs[i] = sdk.AccAddress(keys[i].PubKey().Address())
}
return

View File

@ -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)
}

View File

@ -2,6 +2,7 @@ package main
import (
"encoding/json"
"fmt"
"io"
"github.com/spf13/cobra"
@ -28,7 +29,11 @@ import (
)
// kvd custom flags
const flagInvCheckPeriod = "inv-check-period"
const (
flagInvCheckPeriod = "inv-check-period"
flagMempoolEnableAuth = "mempool.enable-authentication"
flagMempoolAuthAddresses = "mempool.authorized-addresses"
)
var invCheckPeriod uint
@ -72,7 +77,23 @@ func main() {
executor := cli.PrepareBaseCmd(rootCmd, "KA", app.DefaultNodeHome)
rootCmd.PersistentFlags().UintVar(&invCheckPeriod, flagInvCheckPeriod,
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 {
panic(err)
}
@ -95,8 +116,21 @@ func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer) abci.Application
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(
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.SetMinGasPrices(viper.GetString(server.FlagMinGasPrices)),
baseapp.SetHaltHeight(viper.GetUint64(server.FlagHaltHeight)),
@ -110,13 +144,33 @@ func exportAppStateAndTMValidators(
) (json.RawMessage, []tmtypes.GenesisValidator, error) {
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)
if err != nil {
return nil, nil, err
}
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)
}
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
View File

@ -3,12 +3,12 @@ module github.com/kava-labs/kava
go 1.13
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/spf13/cobra v1.0.0
github.com/spf13/viper v1.6.3
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
gopkg.in/yaml.v2 v2.3.0
)

46
go.sum
View File

@ -1,7 +1,7 @@
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=
github.com/99designs/keyring v1.1.3 h1:mEV3iyZWjkxQ7R8ia8GcG97vCX5zQQ7n4o8R2BylwQY=
github.com/99designs/keyring v1.1.3/go.mod h1:657DQuMrBZRtuL/voxVyiyb6zpMehlm5vLB9Qwrv904=
github.com/99designs/keyring v1.1.6 h1:kVDC2uCgVwecxCk+9zoCt2uEL6dt+dfVzMvGgnVcIuM=
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/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
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/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/cosmos/cosmos-sdk v0.39.1 h1:vhjf9PZh9ph8btAj9aBpHoVITgVVjNBpM3x5Gl/Vwac=
github.com/cosmos/cosmos-sdk v0.39.1/go.mod h1:ry2ROl5n+f2/QXpKJo3rdWNJwll00z7KhIVcxNcl16M=
github.com/cosmos/cosmos-sdk v0.39.2 h1:nLfCJMkUuFt7ansi/YvCxwwxLFrgHCA3cYP4sJKYQdk=
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/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
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/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/dvsekhvalnov/jose2go v0.0.0-20180829124132-7f401d37b68a h1:mq+R6XEM6lJX5VlLyZIrUSP8tSuJp82xTK89hvBwJbU=
github.com/dvsekhvalnov/jose2go v0.0.0-20180829124132-7f401d37b68a/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM=
github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b h1:HBah4D48ypg3J7Np4N+HY/ZR76fx3HEUGxDU6Uk39oQ=
github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
@ -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 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
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.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
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 v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
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.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.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 v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
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/reflect2 v0.0.0-20180701023420-4b7aa43c6742/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/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
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.15.1 h1:D2uk35eT4iTsvJd9jWIetzthE5C0/k2QmMFkCN+4JgQ=
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.0/go.mod h1:QmfViflFiXzxKLQE4tAUuWQHq+RSuQFxablW5oJZ6sE=
github.com/tendermint/iavl v0.14.1 h1:jz7YOvGiPwmcqqVMcSMjxCu4WXtQYGhKdKrWTTJ5EKs=
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.7 h1:b5CQD8ggDtl4u0EbXzabi0MaOw9NrcXker6ijEkAE74=
github.com/tendermint/tendermint v0.33.7/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM=
github.com/tendermint/tendermint v0.33.9 h1:rRKIfu5qAXX5f9bwX1oUXSZz/ALFJjDuivhkbGUQxiU=
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/go.mod h1:g92zWjHpCYlEvQXvy9M168Su8V1IBEeawpXVVBaK4f4=
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-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-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/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=
@ -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-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-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-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
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-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-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.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
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-20190308202827-9d24e82272b4/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-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-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.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
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.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
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/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
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.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-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 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/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/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=

View File

@ -139,3 +139,28 @@ func (k Keeper) GetSupplyLimit(ctx sdk.Context, denom string) (types.SupplyLimit
}
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
}

View File

@ -116,6 +116,14 @@ func (suite *ParamsTestSuite) TestGetAssetByCoinID() {
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() {
type args struct {
coin sdk.Coin

View File

@ -59,3 +59,20 @@ func (k Keeper) GetMarket(ctx sdk.Context, marketID string) (types.Market, bool)
}
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
}

View File

@ -11,6 +11,7 @@ import (
tmtime "github.com/tendermint/tendermint/types/time"
"github.com/kava-labs/kava/app"
"github.com/kava-labs/kava/x/pricefeed"
"github.com/kava-labs/kava/x/pricefeed/keeper"
)
@ -38,15 +39,32 @@ func (suite *KeeperTestSuite) SetupTest() {
func (suite *KeeperTestSuite) TestGetSetOracles() {
params := suite.keeper.GetParams(suite.ctx)
suite.Equal([]sdk.AccAddress(nil), params.Markets[0].Oracles)
params.Markets[0].Oracles = suite.addrs
suite.NotPanics(func() { suite.keeper.SetParams(suite.ctx, params) })
params = suite.keeper.GetParams(suite.ctx)
suite.Equal(suite.addrs, params.Markets[0].Oracles)
addr, err := suite.keeper.GetOracle(suite.ctx, params.Markets[0].MarketID, suite.addrs[0])
suite.NoError(err)
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) {
suite.Run(t, new(KeeperTestSuite))
}