From 7b7d45ddd229bc1934e9d3885d068f687dfe7e3a Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 15 Nov 2018 14:30:24 +0000 Subject: [PATCH 1/6] Merge PR #2800: Limit total number of signatures per transaction * Limit total number of signatures per transaction * Fail if limit is exceeded * Loop over all sigs and count subkeys * No need for a type switch, adopt early return * Test rejection logic * Mention sigs limit --- PENDING.md | 1 + docs/reference/baseapp.md | 3 +- types/errors.go | 6 ++++ x/auth/ante.go | 26 ++++++++++++++ x/auth/ante_test.go | 75 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 109 insertions(+), 2 deletions(-) diff --git a/PENDING.md b/PENDING.md index af4a1193b..74395be2d 100644 --- a/PENDING.md +++ b/PENDING.md @@ -13,6 +13,7 @@ BREAKING CHANGES * SDK * [\#2752](https://github.com/cosmos/cosmos-sdk/pull/2752) Don't hardcode bondable denom. + * [\#2019](https://github.com/cosmos/cosmos-sdk/issues/2019) Cap total number of signatures. Current per-transaction limit is 7, and if that is exceeded transaction is rejected. * Tendermint diff --git a/docs/reference/baseapp.md b/docs/reference/baseapp.md index 3eaf1e2f7..1828021c2 100644 --- a/docs/reference/baseapp.md +++ b/docs/reference/baseapp.md @@ -2,8 +2,7 @@ `baseApp` requires stores to be mounted via capabilities keys - handlers can only access stores they're given the key to. The `baseApp` ensures all stores are properly loaded, cached, and committed. One mounted store is considered the "main" - it holds the latest block header, from which we can find and load the most recent state. -`baseApp` distinguishes between two handler types - the `AnteHandler` and the `MsgHandler`. The former is a global validity check (checking nonces, sigs and sufficient balances to pay fees, -e.g. things that apply to all transaction from all modules), the later is the full state transition function. +`baseApp` distinguishes between two handler types: `AnteHandler` and `MsgHandler`. Whilst the former is a global validity check that applies to all transactions from all modules, i.e. it checks nonces and whether balances are sufficient to pay fees, validates signatures and ensures that transactions don't carry too many signatures, the latter is the full state transition function. During CheckTx the state transition function is only applied to the checkTxState and should return before any expensive state transitions are run (this is up to each developer). It also needs to return the estimated gas cost. diff --git a/types/errors.go b/types/errors.go index e05800b53..965a97c87 100644 --- a/types/errors.go +++ b/types/errors.go @@ -57,6 +57,7 @@ const ( CodeOutOfGas CodeType = 12 CodeMemoTooLarge CodeType = 13 CodeInsufficientFee CodeType = 14 + CodeTooManySignatures CodeType = 15 // CodespaceRoot is a codespace for error codes in this file only. // Notice that 0 is an "unset" codespace, which can be overridden with @@ -103,6 +104,8 @@ func CodeToDefaultMsg(code CodeType) string { return "memo too large" case CodeInsufficientFee: return "insufficient fee" + case CodeTooManySignatures: + return "maximum numer of signatures exceeded" default: return unknownCodeMsg(code) } @@ -155,6 +158,9 @@ func ErrMemoTooLarge(msg string) Error { func ErrInsufficientFee(msg string) Error { return newErrorWithRootCodespace(CodeInsufficientFee, msg) } +func ErrTooManySignatures(msg string) Error { + return newErrorWithRootCodespace(CodeTooManySignatures, msg) +} //---------------------------------------- // Error & sdkError diff --git a/x/auth/ante.go b/x/auth/ante.go index e88a20a43..8539be06a 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -4,9 +4,11 @@ import ( "bytes" "encoding/hex" "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/multisig" "github.com/tendermint/tendermint/crypto/secp256k1" ) @@ -17,6 +19,8 @@ const ( maxMemoCharacters = 100 // how much gas = 1 atom gasPerUnitCost = 1000 + // max total number of sigs per tx + txSigLimit = 7 ) // NewAnteHandler returns an AnteHandler that checks @@ -74,6 +78,16 @@ func NewAnteHandler(am AccountKeeper, fck FeeCollectionKeeper) sdk.AnteHandler { stdSigs := stdTx.GetSignatures() // When simulating, this would just be a 0-length slice. signerAddrs := stdTx.GetSigners() + sigCount := 0 + for i := 0; i < len(stdSigs); i++ { + sigCount += countSubKeys(stdSigs[i].PubKey) + if sigCount > txSigLimit { + return newCtx, sdk.ErrTooManySignatures(fmt.Sprintf( + "signatures: %d, limit: %d", sigCount, txSigLimit), + ).Result(), true + } + } + // create the list of all sign bytes signBytesList := getSignBytesList(newCtx.ChainID(), stdTx, stdSigs) signerAccs, res := getSignerAccs(newCtx, am, signerAddrs) @@ -308,3 +322,15 @@ func getSignBytesList(chainID string, stdTx StdTx, stdSigs []StdSignature) (sign } return } + +func countSubKeys(pub crypto.PubKey) int { + v, ok := pub.(*multisig.PubKeyMultisigThreshold) + if !ok { + return 1 + } + nkeys := 0 + for _, subkey := range v.PubKeys { + nkeys += countSubKeys(subkey) + } + return nkeys +} diff --git a/x/auth/ante_test.go b/x/auth/ante_test.go index d29b0bf50..98725a74b 100644 --- a/x/auth/ante_test.go +++ b/x/auth/ante_test.go @@ -10,6 +10,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/multisig" "github.com/tendermint/tendermint/crypto/secp256k1" "github.com/tendermint/tendermint/libs/log" ) @@ -714,3 +715,77 @@ func TestAdjustFeesByGas(t *testing.T) { }) } } + +func TestCountSubkeys(t *testing.T) { + genPubKeys := func(n int) []crypto.PubKey { + var ret []crypto.PubKey + for i := 0; i < n; i++ { + ret = append(ret, secp256k1.GenPrivKey().PubKey()) + } + return ret + } + genMultiKey := func(n, k int, keysGen func(n int) []crypto.PubKey) crypto.PubKey { + return multisig.NewPubKeyMultisigThreshold(k, keysGen(n)) + } + type args struct { + pub crypto.PubKey + } + mkey := genMultiKey(5, 4, genPubKeys) + mkeyType := mkey.(*multisig.PubKeyMultisigThreshold) + mkeyType.PubKeys = append(mkeyType.PubKeys, genMultiKey(6, 5, genPubKeys)) + tests := []struct { + name string + args args + want int + }{ + {"single key", args{secp256k1.GenPrivKey().PubKey()}, 1}, + {"multi sig key", args{genMultiKey(5, 4, genPubKeys)}, 5}, + {"multi multi sig", args{mkey}, 11}, + } + for _, tt := range tests { + t.Run(tt.name, func(T *testing.T) { + require.Equal(t, tt.want, countSubKeys(tt.args.pub)) + }) + } +} + +func TestAnteHandlerSigLimitExceeded(t *testing.T) { + // setup + ms, capKey, capKey2 := setupMultiStore() + cdc := codec.New() + RegisterBaseAccount(cdc) + mapper := NewAccountKeeper(cdc, capKey, ProtoBaseAccount) + feeCollector := NewFeeCollectionKeeper(cdc, capKey2) + anteHandler := NewAnteHandler(mapper, feeCollector) + ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, log.NewNopLogger()) + ctx = ctx.WithBlockHeight(1) + + // keys and addresses + priv1, addr1 := privAndAddr() + priv2, addr2 := privAndAddr() + priv3, addr3 := privAndAddr() + priv4, addr4 := privAndAddr() + priv5, addr5 := privAndAddr() + priv6, addr6 := privAndAddr() + priv7, addr7 := privAndAddr() + priv8, addr8 := privAndAddr() + + // set the accounts + acc1 := mapper.NewAccountWithAddress(ctx, addr1) + acc1.SetCoins(newCoins()) + mapper.SetAccount(ctx, acc1) + acc2 := mapper.NewAccountWithAddress(ctx, addr2) + acc2.SetCoins(newCoins()) + mapper.SetAccount(ctx, acc2) + + var tx sdk.Tx + msg := newTestMsg(addr1, addr2, addr3, addr4, addr5, addr6, addr7, addr8) + msgs := []sdk.Msg{msg} + fee := newStdFee() + + // test rejection logic + privs, accnums, seqs := []crypto.PrivKey{priv1, priv2, priv3, priv4, priv5, priv6, priv7, priv8}, + []int64{0, 0, 0, 0, 0, 0, 0, 0}, []int64{0, 0, 0, 0, 0, 0, 0, 0} + tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeTooManySignatures) +} From 815a6de82f9183585d6f56a045fa61faa59dd7c4 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 15 Nov 2018 18:01:19 +0000 Subject: [PATCH 2/6] R4R: Remove AppInit (#2801) * Remove AppInit * Update PENDING.md --- PENDING.md | 1 + cmd/gaia/app/genesis.go | 8 -------- cmd/gaia/cmd/gaiad/main.go | 8 +++----- cmd/gaia/init/init.go | 2 +- cmd/gaia/init/init_test.go | 16 +++------------- cmd/gaia/init/testnet.go | 3 +-- .../simple-governance/bridging-it-all.md | 7 +------ docs/examples/basecoin/cmd/basecoind/main.go | 10 ++++------ docs/examples/democoin/cmd/democoind/main.go | 15 +++++---------- server/init.go | 11 ----------- server/util.go | 2 +- 11 files changed, 20 insertions(+), 63 deletions(-) diff --git a/PENDING.md b/PENDING.md index 74395be2d..357d1c8b0 100644 --- a/PENDING.md +++ b/PENDING.md @@ -14,6 +14,7 @@ BREAKING CHANGES * SDK * [\#2752](https://github.com/cosmos/cosmos-sdk/pull/2752) Don't hardcode bondable denom. * [\#2019](https://github.com/cosmos/cosmos-sdk/issues/2019) Cap total number of signatures. Current per-transaction limit is 7, and if that is exceeded transaction is rejected. + * [\#2801](https://github.com/cosmos/cosmos-sdk/pull/2801) Remove AppInit structure. * Tendermint diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index e3c869ada..7d95bbfa7 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -11,7 +11,6 @@ import ( "strings" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" distr "github.com/cosmos/cosmos-sdk/x/distribution" @@ -92,13 +91,6 @@ func (ga *GenesisAccount) ToAccount() (acc *auth.BaseAccount) { } } -// get app init parameters for server init command -func GaiaAppInit() server.AppInit { - - return server.AppInit{ - AppGenState: GaiaAppGenStateJSON, - } -} // Create the core parameters for genesis initialization for gaia // note that the pubkey input is this machines pubkey diff --git a/cmd/gaia/cmd/gaiad/main.go b/cmd/gaia/cmd/gaiad/main.go index 2a72b42cc..bea3ac952 100644 --- a/cmd/gaia/cmd/gaiad/main.go +++ b/cmd/gaia/cmd/gaiad/main.go @@ -37,15 +37,13 @@ func main() { Short: "Gaia Daemon (server)", PersistentPreRunE: server.PersistentPreRunEFn(ctx), } - appInit := app.GaiaAppInit() - rootCmd.AddCommand(gaiaInit.InitCmd(ctx, cdc, appInit)) + rootCmd.AddCommand(gaiaInit.InitCmd(ctx, cdc)) rootCmd.AddCommand(gaiaInit.CollectGenTxsCmd(ctx, cdc)) - rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, server.AppInit{})) + rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc)) rootCmd.AddCommand(gaiaInit.GenTxCmd(ctx, cdc)) rootCmd.AddCommand(gaiaInit.AddGenesisAccountCmd(ctx, cdc)) - server.AddCommands(ctx, cdc, rootCmd, appInit, - newApp, exportAppStateAndTMValidators) + server.AddCommands(ctx, cdc, rootCmd, newApp, exportAppStateAndTMValidators) // prepare and add flags executor := cli.PrepareBaseCmd(rootCmd, "GA", app.DefaultNodeHome) diff --git a/cmd/gaia/init/init.go b/cmd/gaia/init/init.go index 1f12da6bd..19179233a 100644 --- a/cmd/gaia/init/init.go +++ b/cmd/gaia/init/init.go @@ -42,7 +42,7 @@ func displayInfo(cdc *codec.Codec, info printInfo) error { // get cmd to initialize all files for tendermint and application // nolint -func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cobra.Command { +func InitCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "init", Short: "Initialize private validator, p2p, genesis, and application configuration files", diff --git a/cmd/gaia/init/init_test.go b/cmd/gaia/init/init_test.go index d1d9b9ce2..1eeba66ae 100644 --- a/cmd/gaia/init/init_test.go +++ b/cmd/gaia/init/init_test.go @@ -32,10 +32,7 @@ func TestInitCmd(t *testing.T) { ctx := server.NewContext(cfg, logger) cdc := app.MakeCodec() - appInit := server.AppInit{ - AppGenState: mock.AppGenState, - } - cmd := InitCmd(ctx, cdc, appInit) + cmd := InitCmd(ctx, cdc) viper.Set(flagMoniker, "gaianode-test") @@ -65,13 +62,9 @@ func TestEmptyState(t *testing.T) { ctx := server.NewContext(cfg, logger) cdc := app.MakeCodec() - appInit := server.AppInit{ - AppGenState: mock.AppGenStateEmpty, - } - viper.Set(flagMoniker, "gaianode-test") - cmd := InitCmd(ctx, cdc, appInit) + cmd := InitCmd(ctx, cdc) err = cmd.RunE(nil, nil) require.NoError(t, err) @@ -116,10 +109,7 @@ func TestStartStandAlone(t *testing.T) { require.Nil(t, err) ctx := server.NewContext(cfg, logger) cdc := app.MakeCodec() - appInit := server.AppInit{ - AppGenState: mock.AppGenState, - } - initCmd := InitCmd(ctx, cdc, appInit) + initCmd := InitCmd(ctx, cdc) err = initCmd.RunE(nil, nil) require.NoError(t, err) diff --git a/cmd/gaia/init/testnet.go b/cmd/gaia/init/testnet.go index b0676515c..73a7cea14 100644 --- a/cmd/gaia/init/testnet.go +++ b/cmd/gaia/init/testnet.go @@ -38,8 +38,7 @@ var ( const nodeDirPerm = 0755 // get cmd to initialize all files for tendermint testnet and application -func TestnetFilesCmd(ctx *server.Context, cdc *codec.Codec, - appInit server.AppInit) *cobra.Command { +func TestnetFilesCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "testnet", diff --git a/docs/_attic/sdk/sdk-by-examples/simple-governance/bridging-it-all.md b/docs/_attic/sdk/sdk-by-examples/simple-governance/bridging-it-all.md index 546eb7d87..a90a6913e 100644 --- a/docs/_attic/sdk/sdk-by-examples/simple-governance/bridging-it-all.md +++ b/docs/_attic/sdk/sdk-by-examples/simple-governance/bridging-it-all.md @@ -98,11 +98,6 @@ The `simplegovd` command will run the daemon server as a background process. Fir ```go // cmd/simplegovd/main.go -// SimpleGovAppInit initial parameters -var SimpleGovAppInit = server.AppInit{ - AppGenState: SimpleGovAppGenState, - AppGenTx: server.SimpleAppGenTx, -} // SimpleGovAppGenState sets up the app_state and appends the simpleGov app state func SimpleGovAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (appState json.RawMessage, err error) { @@ -137,7 +132,7 @@ func main() { PersistentPreRunE: server.PersistentPreRunEFn(ctx), } - server.AddCommands(ctx, cdc, rootCmd, SimpleGovAppInit, + server.AddCommands(ctx, cdc, rootCmd, server.ConstructAppCreator(newApp, "simplegov"), server.ConstructAppExporter(exportAppState, "simplegov")) diff --git a/docs/examples/basecoin/cmd/basecoind/main.go b/docs/examples/basecoin/cmd/basecoind/main.go index 731c5135f..318b36a8f 100644 --- a/docs/examples/basecoin/cmd/basecoind/main.go +++ b/docs/examples/basecoin/cmd/basecoind/main.go @@ -39,11 +39,9 @@ func main() { PersistentPreRunE: server.PersistentPreRunEFn(ctx), } - appInit := server.DefaultAppInit - rootCmd.AddCommand(InitCmd(ctx, cdc, appInit)) + rootCmd.AddCommand(InitCmd(ctx, cdc)) - server.AddCommands(ctx, cdc, rootCmd, appInit, - newApp, exportAppStateAndTMValidators) + server.AddCommands(ctx, cdc, rootCmd, newApp, exportAppStateAndTMValidators) // prepare and add flags rootDir := os.ExpandEnv("$HOME/.basecoind") @@ -58,7 +56,7 @@ func main() { // get cmd to initialize all files for tendermint and application // nolint: errcheck -func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cobra.Command { +func InitCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "init", Short: "Initialize genesis config, priv-validator file, and p2p-node file", @@ -84,7 +82,7 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob return err } - appState, err := appInit.AppGenState( + appState, err := server.SimpleAppGenState( cdc, tmtypes.GenesisDoc{}, []json.RawMessage{genTx}) if err != nil { return err diff --git a/docs/examples/democoin/cmd/democoind/main.go b/docs/examples/democoin/cmd/democoind/main.go index 506d888a5..29e2640fd 100644 --- a/docs/examples/democoin/cmd/democoind/main.go +++ b/docs/examples/democoin/cmd/democoind/main.go @@ -30,10 +30,6 @@ const ( flagClientHome = "home-client" ) -// init parameters -var CoolAppInit = server.AppInit{ - AppGenState: CoolAppGenState, -} // coolGenAppParams sets up the app_state and appends the cool app state func CoolAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) ( @@ -65,7 +61,7 @@ func CoolAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []js // get cmd to initialize all files for tendermint and application // nolint: errcheck -func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cobra.Command { +func InitCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "init", Short: "Initialize genesis config, priv-validator file, and p2p-node file", @@ -91,7 +87,7 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob return err } - appState, err := appInit.AppGenState(cdc, tmtypes.GenesisDoc{}, + appState, err := CoolAppGenState(cdc, tmtypes.GenesisDoc{}, []json.RawMessage{genTx}) if err != nil { return err @@ -157,11 +153,10 @@ func main() { PersistentPreRunE: server.PersistentPreRunEFn(ctx), } - rootCmd.AddCommand(InitCmd(ctx, cdc, CoolAppInit)) - rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, CoolAppInit)) + rootCmd.AddCommand(InitCmd(ctx, cdc)) + rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc)) - server.AddCommands(ctx, cdc, rootCmd, CoolAppInit, - newApp, exportAppStateAndTMValidators) + server.AddCommands(ctx, cdc, rootCmd, newApp, exportAppStateAndTMValidators) // prepare and add flags rootDir := os.ExpandEnv("$HOME/.democoind") diff --git a/server/init.go b/server/init.go index 75e13f452..3a6c6adae 100644 --- a/server/init.go +++ b/server/init.go @@ -15,13 +15,6 @@ import ( tmtypes "github.com/tendermint/tendermint/types" ) -// Core functionality passed from the application to the server init command -type AppInit struct { - // AppGenState creates the core parameters initialization. It takes in a - // pubkey meant to represent the pubkey of the validator of this machine. - AppGenState func(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) ( - appState json.RawMessage, err error) -} // SimpleGenTx is a simple genesis tx type SimpleGenTx struct { @@ -30,10 +23,6 @@ type SimpleGenTx struct { //_____________________________________________________________________ -// simple default application init -var DefaultAppInit = AppInit{ - AppGenState: SimpleAppGenState, -} // Generate a genesis transaction func SimpleAppGenTx(cdc *codec.Codec, pk crypto.PubKey) ( diff --git a/server/util.go b/server/util.go index 633ad8870..3d4a9d0b6 100644 --- a/server/util.go +++ b/server/util.go @@ -129,7 +129,7 @@ func validateConfig(conf *cfg.Config) error { // add server commands func AddCommands( ctx *Context, cdc *codec.Codec, - rootCmd *cobra.Command, appInit AppInit, + rootCmd *cobra.Command, appCreator AppCreator, appExport AppExporter) { rootCmd.PersistentFlags().String("log_level", ctx.Config.LogLevel, "Log level") From e04d32c8d5c2fe88def017eaafcc9f68c051ce38 Mon Sep 17 00:00:00 2001 From: gamarin2 Date: Thu, 15 Nov 2018 20:54:54 +0100 Subject: [PATCH 3/6] DOCS: fix links and add cli to sidebar (#2830) * fix links and add cli to sidebar --- README.md | 2 +- docs/.vuepress/config.js | 7 ++++--- docs/gaia/join-testnet.md | 8 ++++---- docs/intro/README.md | 4 ++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 3540dbe3d..dec4106bc 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ [![riot.im](https://img.shields.io/badge/riot.im-JOIN%20CHAT-green.svg)](https://riot.im/app/#/room/#cosmos-sdk:matrix.org) The Cosmos-SDK is a framework for building blockchain applications in Golang. -It is being used to build `Gaia`, the first implementation of the [Cosmos Hub](https://cosmos.network/docs/), +It is being used to build `Gaia`, the first implementation of the Cosmos Hub. **WARNING**: The SDK has mostly stabilized, but we are still making some breaking changes. diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index c4710379e..5fb13f47b 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -26,12 +26,13 @@ module.exports = { children: [ "/gaia/installation", "/gaia/join-testnet", - "/gaia/networks", + "/gaia/validators/validator-setup", "/gaia/validators/overview", "/gaia/validators/security", "/gaia/validators/validator-faq", - "/gaia/validators/validator-setup", - "/gaia/ledger" + "/gaia/networks", + "/gaia/ledger", + "/gaia/gaiacli" ] }, { diff --git a/docs/gaia/join-testnet.md b/docs/gaia/join-testnet.md index bdbff65e2..e1c9163cd 100644 --- a/docs/gaia/join-testnet.md +++ b/docs/gaia/join-testnet.md @@ -17,18 +17,18 @@ These instructions are for setting up a brand new full node from scratch. First, initialize the node and create the necessary config files: ```bash -gaiad init +gaiad init --moniker ``` ::: warning Note -Only ASCII characters are supported for the `--name`. Using Unicode characters will render your node unreachable. +Only ASCII characters are supported for the `--moniker`. Using Unicode characters will render your node unreachable. ::: -You can edit this `name` later, in the `~/.gaiad/config/config.toml` file: +You can edit this `moniker` later, in the `~/.gaiad/config/config.toml` file: ```toml # A custom human readable name for this node -moniker = "" +moniker = "" ``` You can edit the `~/.gaiad/config/gaiad.toml` file in order to enable the anti spam mechanism and reject incoming transactions with less than a minimum fee: diff --git a/docs/intro/README.md b/docs/intro/README.md index 83dcc31c5..54d8bfce1 100644 --- a/docs/intro/README.md +++ b/docs/intro/README.md @@ -8,11 +8,11 @@ It is based on two major principles: - **Composability:** Anyone can create a module for the Cosmos-SDK, and integrating the already-built modules is as simple as importing them into your blockchain application. -- **Capabilities:** The SDK is inspired by capabilities-based security, and informed by years of wrestling with blockchain state-machines. Most developers will need to access other 3rd party modules when building their own modules. Given that the Cosmos-SDK is an open framework, some of the modules may be malicious, which means there is a need for security principles to reason about inter-module interactions. These principles are based on object-cababilities. In practice, this means that instead of having each module keep an access control list for other modules, each module implements special objects called keepers that can be passed to other modules to grant a pre-defined set of capabilities. For example, if an instance of module A's keepers is passed to module B, the latter will be able to call a restricted set of module A's functions. The capabilities of each keeper are defined by the module's developer, and it's the developer's job to understand and audit the safety of foreign code from 3rd party modules based on the capabilities they are passing into each third party module. For a deeper look at capabilities, jump to [this section](./capabilities.md). +- **Capabilities:** The SDK is inspired by capabilities-based security, and informed by years of wrestling with blockchain state-machines. Most developers will need to access other 3rd party modules when building their own modules. Given that the Cosmos-SDK is an open framework, some of the modules may be malicious, which means there is a need for security principles to reason about inter-module interactions. These principles are based on object-cababilities. In practice, this means that instead of having each module keep an access control list for other modules, each module implements special objects called keepers that can be passed to other modules to grant a pre-defined set of capabilities. For example, if an instance of module A's keepers is passed to module B, the latter will be able to call a restricted set of module A's functions. The capabilities of each keeper are defined by the module's developer, and it's the developer's job to understand and audit the safety of foreign code from 3rd party modules based on the capabilities they are passing into each third party module. For a deeper look at capabilities, jump to [this section](./ocap.md). ## Learn more about the SDK -- [SDK application architecture](./design.md) +- [SDK application architecture](./sdk-app-architecture.md) - [SDK security paradigm: ocap](./ocap.md) ## Creating a new SDK project From cf6b7ef6d85781100e254cb535724c085ef74df9 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 15 Nov 2018 22:21:42 +0100 Subject: [PATCH 4/6] Test runtime-assertable invariants every block (#2807) * Initial pass * Minor cleanup --- PENDING.md | 1 + cmd/gaia/app/app.go | 2 ++ cmd/gaia/app/invariants.go | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 cmd/gaia/app/invariants.go diff --git a/PENDING.md b/PENDING.md index 357d1c8b0..ba90d3ac8 100644 --- a/PENDING.md +++ b/PENDING.md @@ -34,6 +34,7 @@ FEATURES * [app] \#2791 Support export at a specific height, with `gaiad export --height=HEIGHT`. * [x/gov] [#2479](https://github.com/cosmos/cosmos-sdk/issues/2479) Implemented querier for getting governance parameters. + * [app] \#2663 - Runtime-assertable invariants * [app] \#2791 Support export at a specific height, with `gaiad export --height=HEIGHT`. * SDK diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 25265a361..fb8455b5a 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -210,6 +210,8 @@ func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.R tags := gov.EndBlocker(ctx, app.govKeeper) validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper) + app.assertRuntimeInvariants() + return abci.ResponseEndBlock{ ValidatorUpdates: validatorUpdates, Tags: tags, diff --git a/cmd/gaia/app/invariants.go b/cmd/gaia/app/invariants.go new file mode 100644 index 000000000..67ec1c714 --- /dev/null +++ b/cmd/gaia/app/invariants.go @@ -0,0 +1,34 @@ +package app + +import ( + "fmt" + "time" + + banksim "github.com/cosmos/cosmos-sdk/x/bank/simulation" + distrsim "github.com/cosmos/cosmos-sdk/x/distribution/simulation" + "github.com/cosmos/cosmos-sdk/x/mock/simulation" + stakesim "github.com/cosmos/cosmos-sdk/x/stake/simulation" +) + +func (app *GaiaApp) runtimeInvariants() []simulation.Invariant { + return []simulation.Invariant{ + banksim.NonnegativeBalanceInvariant(app.accountKeeper), + distrsim.ValAccumInvariants(app.distrKeeper, app.stakeKeeper), + stakesim.SupplyInvariants(app.bankKeeper, app.stakeKeeper, + app.feeCollectionKeeper, app.distrKeeper, app.accountKeeper), + stakesim.PositivePowerInvariant(app.stakeKeeper), + } +} + +func (app *GaiaApp) assertRuntimeInvariants() { + invariants := app.runtimeInvariants() + start := time.Now() + for _, inv := range invariants { + if err := inv(app.BaseApp); err != nil { + panic(fmt.Errorf("invariant broken: %s", err)) + } + } + end := time.Now() + diff := end.Sub(start) + app.BaseApp.Logger.With("module", "invariants").Info("Asserted all invariants", "duration", diff) +} From f2b38874ef04d22d2c93c737d78f62e8673e59b3 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 16 Nov 2018 05:01:34 +0000 Subject: [PATCH 5/6] Check whether key passed with --name exists before redirecting to tx create-validator Closes: #2804 --- cmd/gaia/init/gentx.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cmd/gaia/init/gentx.go b/cmd/gaia/init/gentx.go index 449eb2b85..6d66f2e30 100644 --- a/cmd/gaia/init/gentx.go +++ b/cmd/gaia/init/gentx.go @@ -3,6 +3,7 @@ package init import ( "fmt" "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/cmd/gaia/app" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/server" @@ -61,6 +62,14 @@ following delegation and commission default parameters: return err } + kb, err := keys.GetKeyBaseFromDir(viper.GetString(flagClientHome)) + if err != nil { + return err + } + if _, err = kb.Get(viper.GetString(client.FlagName)); err != nil { + return err + } + // Read --pubkey, if empty take it from priv_validator.json if valPubKeyString := viper.GetString(cli.FlagPubKey); valPubKeyString != "" { valPubKey, err = sdk.GetConsPubKeyBech32(valPubKeyString) From 9beb6d405e9c3d8ac752e74973236d0d546407a3 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 16 Nov 2018 05:05:20 +0000 Subject: [PATCH 6/6] Update PENDING.md --- PENDING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PENDING.md b/PENDING.md index 74395be2d..f58a8f543 100644 --- a/PENDING.md +++ b/PENDING.md @@ -8,6 +8,7 @@ BREAKING CHANGES * [cli] [\#2728](https://github.com/cosmos/cosmos-sdk/pull/2728) Seperate `tx` and `query` subcommands by module * [cli] [\#2727](https://github.com/cosmos/cosmos-sdk/pull/2727) Fix unbonding command flow * [cli] [\#2786](https://github.com/cosmos/cosmos-sdk/pull/2786) Fix redelegation command flow + * [cli] [\#2804](https://github.com/cosmos/cosmos-sdk/issues/2804) Check whether key exists before passing it on to `tx create-validator`. * Gaia