Merge branch 'develop' into dev/sim_msg_edit_val

This commit is contained in:
Christopher Goes 2018-11-05 11:45:53 +01:00
commit cb3cb27b81
102 changed files with 1301 additions and 921 deletions

View File

@ -752,7 +752,7 @@ Update to Tendermint v0.19.4 (fixes a consensus bug and improves logging)
BREAKING CHANGES BREAKING CHANGES
* [stake] MarshalJSON -> MarshalBinary * [stake] MarshalJSON -> MarshalBinaryLengthPrefixed
* Queries against the store must be prefixed with the path "/store" * Queries against the store must be prefixed with the path "/store"
FEATURES FEATURES

74
Gopkg.lock generated
View File

@ -10,6 +10,7 @@
revision = "48b08affede2cea076a3cf13b2e3f72ed262b743" revision = "48b08affede2cea076a3cf13b2e3f72ed262b743"
[[projects]] [[projects]]
branch = "master"
digest = "1:09a7f74eb6bb3c0f14d8926610c87f569c5cff68e978d30e9a3540aeb626fdf0" digest = "1:09a7f74eb6bb3c0f14d8926610c87f569c5cff68e978d30e9a3540aeb626fdf0"
name = "github.com/bartekn/go-bip39" name = "github.com/bartekn/go-bip39"
packages = ["."] packages = ["."]
@ -38,7 +39,7 @@
name = "github.com/btcsuite/btcd" name = "github.com/btcsuite/btcd"
packages = ["btcec"] packages = ["btcec"]
pruneopts = "UT" pruneopts = "UT"
revision = "2a560b2036bee5e3679ec2133eb6520b2f195213" revision = "67e573d211ace594f1366b4ce9d39726c4b19bd0"
[[projects]] [[projects]]
digest = "1:386de157f7d19259a7f9c81f26ce011223ce0f090353c1152ffdf730d7d10ac2" digest = "1:386de157f7d19259a7f9c81f26ce011223ce0f090353c1152ffdf730d7d10ac2"
@ -62,13 +63,6 @@
revision = "346938d642f2ec3594ed81d874461961cd0faa76" revision = "346938d642f2ec3594ed81d874461961cd0faa76"
version = "v1.1.0" version = "v1.1.0"
[[projects]]
digest = "1:c7644c73a3d23741fdba8a99b1464e021a224b7e205be497271a8003a15ca41b"
name = "github.com/ebuchman/fail-test"
packages = ["."]
pruneopts = "UT"
revision = "95f809107225be108efcf10a3509e4ea6ceef3c4"
[[projects]] [[projects]]
digest = "1:abeb38ade3f32a92943e5be54f55ed6d6e3b6602761d74b4aab4c9dd45c18abd" digest = "1:abeb38ade3f32a92943e5be54f55ed6d6e3b6602761d74b4aab4c9dd45c18abd"
name = "github.com/fsnotify/fsnotify" name = "github.com/fsnotify/fsnotify"
@ -171,12 +165,13 @@
version = "v1.2.0" version = "v1.2.0"
[[projects]] [[projects]]
digest = "1:ea40c24cdbacd054a6ae9de03e62c5f252479b96c716375aace5c120d68647c8" digest = "1:c0d19ab64b32ce9fe5cf4ddceba78d5bc9807f0016db6b1183599da3dcc24d10"
name = "github.com/hashicorp/hcl" name = "github.com/hashicorp/hcl"
packages = [ packages = [
".", ".",
"hcl/ast", "hcl/ast",
"hcl/parser", "hcl/parser",
"hcl/printer",
"hcl/scanner", "hcl/scanner",
"hcl/strconv", "hcl/strconv",
"hcl/token", "hcl/token",
@ -245,12 +240,12 @@
version = "v1.0.0" version = "v1.0.0"
[[projects]] [[projects]]
digest = "1:e32dfc6abff6a3633ef4d9a1022fd707c8ef26f1e1e8f855dc58dc415ce7c8f3" digest = "1:53bc4cd4914cd7cd52139990d5170d6dc99067ae31c56530621b18b35fc30318"
name = "github.com/mitchellh/mapstructure" name = "github.com/mitchellh/mapstructure"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "fe40af7a9c397fa3ddba203c38a5042c5d0475ad" revision = "3536a929edddb9a5b34bd6861dc4a9647cb459fe"
version = "v1.1.1" version = "v1.1.2"
[[projects]] [[projects]]
digest = "1:95741de3af260a92cc5c7f3f3061e85273f5a81b5db20d4bd68da74bd521675e" digest = "1:95741de3af260a92cc5c7f3f3061e85273f5a81b5db20d4bd68da74bd521675e"
@ -296,7 +291,7 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5" digest = "1:db712fde5d12d6cdbdf14b777f0c230f4ff5ab0be8e35b239fc319953ed577a4"
name = "github.com/prometheus/common" name = "github.com/prometheus/common"
packages = [ packages = [
"expfmt", "expfmt",
@ -304,11 +299,11 @@
"model", "model",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "c7de2306084e37d54b8be01f3541a8464345e9a5" revision = "7e9e6cabbd393fc208072eedef99188d0ce788b6"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:ef1dd9945e58ee9b635273d28c0ef3fa3742a7dedc038ebe207fd63e6ce000ef" digest = "1:ef74914912f99c79434d9c09658274678bc85080ebe3ab32bec3940ebce5e1fc"
name = "github.com/prometheus/procfs" name = "github.com/prometheus/procfs"
packages = [ packages = [
".", ".",
@ -317,7 +312,7 @@
"xfs", "xfs",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "418d78d0b9a7b7de3a6bbc8a23def624cc977bb2" revision = "185b4288413d2a0dd0806f78c90dde719829e5ae"
[[projects]] [[projects]]
digest = "1:ea0700160aca4ef099f4e06686a665a87691f4248dddd40796925eda2e46bd64" digest = "1:ea0700160aca4ef099f4e06686a665a87691f4248dddd40796925eda2e46bd64"
@ -346,12 +341,12 @@
version = "v1.1.2" version = "v1.1.2"
[[projects]] [[projects]]
digest = "1:516e71bed754268937f57d4ecb190e01958452336fa73dbac880894164e91c1f" digest = "1:08d65904057412fc0270fc4812a1c90c594186819243160dc779a402d4b6d0bc"
name = "github.com/spf13/cast" name = "github.com/spf13/cast"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "8965335b8c7107321228e3e3702cab9832751bac" revision = "8c9545af88b134710ab1cd196795e7f2388358d7"
version = "v1.2.0" version = "v1.3.0"
[[projects]] [[projects]]
digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e" digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e"
@ -370,12 +365,12 @@
version = "v1.0.0" version = "v1.0.0"
[[projects]] [[projects]]
digest = "1:dab83a1bbc7ad3d7a6ba1a1cc1760f25ac38cdf7d96a5cdd55cd915a4f5ceaf9" digest = "1:c1b1102241e7f645bc8e0c22ae352e8f0dc6484b6cb4d132fa9f24174e0119e2"
name = "github.com/spf13/pflag" name = "github.com/spf13/pflag"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "9a97c102cda95a86cec2345a6f09f55a939babf5" revision = "298182f68c66c05229eb03ac171abe6e309ee79a"
version = "v1.0.2" version = "v1.0.3"
[[projects]] [[projects]]
digest = "1:f8e1a678a2571e265f4bf91a3e5e32aa6b1474a55cb0ea849750cc177b664d96" digest = "1:f8e1a678a2571e265f4bf91a3e5e32aa6b1474a55cb0ea849750cc177b664d96"
@ -424,35 +419,23 @@
revision = "e5840949ff4fff0c56f9b6a541e22b63581ea9df" revision = "e5840949ff4fff0c56f9b6a541e22b63581ea9df"
[[projects]] [[projects]]
branch = "master" digest = "1:10b3a599325740c84a7c81f3f3cb2e1fdb70b3ea01b7fa28495567a2519df431"
digest = "1:087aaa7920e5d0bf79586feb57ce01c35c830396ab4392798112e8aae8c47722"
name = "github.com/tendermint/ed25519"
packages = [
".",
"edwards25519",
"extra25519",
]
pruneopts = "UT"
revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057"
[[projects]]
digest = "1:2c971a45c89ca2ccc735af50919cdee05fbdc54d4bf50625073693300e31ead8"
name = "github.com/tendermint/go-amino" name = "github.com/tendermint/go-amino"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "faa6e731944e2b7b6a46ad202902851e8ce85bee" revision = "6dcc6ddc143e116455c94b25c1004c99e0d0ca12"
version = "v0.12.0" version = "v0.14.0"
[[projects]] [[projects]]
digest = "1:53397098d6acb7613358683cc84ae59281a60c6033f0bff62fa8d3f279c6c430" digest = "1:9f8c4c93658315a795ffd3e0c943d39f78067dd8382b8d7bcfaf6686b92f3978"
name = "github.com/tendermint/iavl" name = "github.com/tendermint/iavl"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "3acc91fb8811db2c5409a855ae1f8e441fe98e2d" revision = "fa74114f764f9827c4ad5573f990ed25bf8c4bac"
version = "v0.11.0" version = "v0.11.1"
[[projects]] [[projects]]
digest = "1:f9c7a1f3ee087476f4883c33cc7c1bdbe56b9670b2fb27855ea2f386393272f5" digest = "1:92d7d1678577fd1a6f3348168cef87880bbc710ef5f4e9a1216f45c56567d734"
name = "github.com/tendermint/tendermint" name = "github.com/tendermint/tendermint"
packages = [ packages = [
"abci/client", "abci/client",
@ -485,6 +468,7 @@
"libs/db", "libs/db",
"libs/errors", "libs/errors",
"libs/events", "libs/events",
"libs/fail",
"libs/flowrate", "libs/flowrate",
"libs/log", "libs/log",
"libs/pubsub", "libs/pubsub",
@ -505,7 +489,6 @@
"rpc/core", "rpc/core",
"rpc/core/types", "rpc/core/types",
"rpc/grpc", "rpc/grpc",
"rpc/lib",
"rpc/lib/client", "rpc/lib/client",
"rpc/lib/server", "rpc/lib/server",
"rpc/lib/types", "rpc/lib/types",
@ -518,8 +501,7 @@
"version", "version",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "90eda9bfb6e6daeed1c8015df41cb36772d91778" revision = "ebee4377b15f2958b08994485375dd2ee8a649ac"
version = "v0.25.1-rc0"
[[projects]] [[projects]]
digest = "1:7886f86064faff6f8d08a3eb0e8c773648ff5a2e27730831e2bfbf07467f6666" digest = "1:7886f86064faff6f8d08a3eb0e8c773648ff5a2e27730831e2bfbf07467f6666"
@ -530,13 +512,15 @@
version = "v0.1.0" version = "v0.1.0"
[[projects]] [[projects]]
digest = "1:aaff04fa01d9b824fde6799759cc597b3ac3671b9ad31924c28b6557d0ee5284" digest = "1:6f6dc6060c4e9ba73cf28aa88f12a69a030d3d19d518ef8e931879eaa099628d"
name = "golang.org/x/crypto" name = "golang.org/x/crypto"
packages = [ packages = [
"bcrypt", "bcrypt",
"blowfish", "blowfish",
"chacha20poly1305", "chacha20poly1305",
"curve25519", "curve25519",
"ed25519",
"ed25519/internal/edwards25519",
"hkdf", "hkdf",
"internal/chacha20", "internal/chacha20",
"internal/subtle", "internal/subtle",

View File

@ -1,24 +1,3 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true
[[constraint]] [[constraint]]
name = "github.com/bgentry/speakeasy" name = "github.com/bgentry/speakeasy"
version = "~0.1.0" version = "~0.1.0"
@ -49,15 +28,15 @@
[[override]] [[override]]
name = "github.com/tendermint/go-amino" name = "github.com/tendermint/go-amino"
version = "=v0.12.0" version = "v0.14.0"
[[override]] [[override]]
name = "github.com/tendermint/iavl" name = "github.com/tendermint/iavl"
version = "=v0.11.0" version = "=v0.11.1"
[[override]] [[override]]
name = "github.com/tendermint/tendermint" name = "github.com/tendermint/tendermint"
version = "=0.25.1-rc0" revision = "ebee4377b15f2958b08994485375dd2ee8a649ac" # TODO replace w/ 0.26.1
## deps without releases: ## deps without releases:
@ -89,7 +68,6 @@
version = "1.0.0" version = "1.0.0"
## transitive deps, without releases: ## transitive deps, without releases:
#
[[override]] [[override]]
name = "github.com/syndtr/goleveldb" name = "github.com/syndtr/goleveldb"

View File

@ -7,12 +7,13 @@ BREAKING CHANGES
* Gaia CLI (`gaiacli`) * Gaia CLI (`gaiacli`)
* Gaia * Gaia
* [gaiad init] \#2602 New genesis workflow
* SDK * SDK
* [simulation] \#2665 only argument to simulation.Invariant is now app * [simulation] \#2665 only argument to simulation.Invariant is now app
* Tendermint * Tendermint
* Upgrade to version 0.26.0
FEATURES FEATURES
@ -42,11 +43,15 @@ IMPROVEMENTS
* Gaia * Gaia
* SDK * SDK
- #2573 [x/distribution] add accum invariance - \#2573 [x/distribution] add accum invariance
- \#2556 [x/mock/simulation] Fix debugging output
- \#2396 [x/mock/simulation] Change parameters to get more slashes
- \#2617 [x/mock/simulation] Randomize all genesis parameters
- \#2669 [x/stake] Added invarant check to make sure validator's power aligns with its spot in the power store.
- \#1924 [x/mock/simulation] Use a transition matrix for block size - \#1924 [x/mock/simulation] Use a transition matrix for block size
- \#2660 [x/mock/simulation] Staking transactions get tested far more frequently - \#2660 [x/mock/simulation] Staking transactions get tested far more frequently
- #2610 [x/stake] Block redelegation to and from the same validator - \#2610 [x/stake] Block redelegation to and from the same validator
- #2652 [x/auth] Add benchmark for get and set account - \#2652 [x/auth] Add benchmark for get and set account
* Tendermint * Tendermint
@ -58,9 +63,10 @@ BUG FIXES
* Gaia CLI (`gaiacli`) * Gaia CLI (`gaiacli`)
* Gaia * Gaia
- \#2670 [x/stake] fixed incorrent `IterateBondedValidators` and split into two functions: `IterateBondedValidators` and `IterateLastBlockConsValidators`
* SDK * SDK
- #2625 [x/gov] fix AppendTag function usage error - \#2625 [x/gov] fix AppendTag function usage error
- \#2677 [x/stake, x/distribution] various staking/distribution fixes as found by the simulator
* Tendermint * Tendermint

View File

@ -337,7 +337,7 @@ func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) (res abc
} }
// Encode with json // Encode with json
value := codec.Cdc.MustMarshalBinary(result) value := codec.Cdc.MustMarshalBinaryLengthPrefixed(result)
return abci.ResponseQuery{ return abci.ResponseQuery{
Code: uint32(sdk.ABCICodeOK), Code: uint32(sdk.ABCICodeOK),
Value: value, Value: value,
@ -394,6 +394,7 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res
ctx := sdk.NewContext(app.cms.CacheMultiStore(), app.checkState.ctx.BlockHeader(), true, app.Logger). ctx := sdk.NewContext(app.cms.CacheMultiStore(), app.checkState.ctx.BlockHeader(), true, app.Logger).
WithMinimumFees(app.minimumFees) WithMinimumFees(app.minimumFees)
// Passes the rest of the path as an argument to the querier. // Passes the rest of the path as an argument to the querier.
// For example, in the path "custom/gov/proposal/test", the gov querier gets []string{"proposal", "test"} as the path // For example, in the path "custom/gov/proposal/test", the gov querier gets []string{"proposal", "test"} as the path
resBytes, err := querier(ctx, path[2:], req) resBytes, err := querier(ctx, path[2:], req)

View File

@ -358,7 +358,7 @@ func testTxDecoder(cdc *codec.Codec) sdk.TxDecoder {
if len(txBytes) == 0 { if len(txBytes) == 0 {
return nil, sdk.ErrTxDecode("txBytes are empty") return nil, sdk.ErrTxDecode("txBytes are empty")
} }
err := cdc.UnmarshalBinary(txBytes, &tx) err := cdc.UnmarshalBinaryLengthPrefixed(txBytes, &tx)
if err != nil { if err != nil {
return nil, sdk.ErrTxDecode("").TraceSDK(err.Error()) return nil, sdk.ErrTxDecode("").TraceSDK(err.Error())
} }
@ -455,7 +455,7 @@ func TestCheckTx(t *testing.T) {
for i := int64(0); i < nTxs; i++ { for i := int64(0); i < nTxs; i++ {
tx := newTxCounter(i, 0) tx := newTxCounter(i, 0)
txBytes, err := codec.MarshalBinary(tx) txBytes, err := codec.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err) require.NoError(t, err)
r := app.CheckTx(txBytes) r := app.CheckTx(txBytes)
assert.True(t, r.IsOK(), fmt.Sprintf("%v", r)) assert.True(t, r.IsOK(), fmt.Sprintf("%v", r))
@ -503,7 +503,7 @@ func TestDeliverTx(t *testing.T) {
for i := 0; i < txPerHeight; i++ { for i := 0; i < txPerHeight; i++ {
counter := int64(blockN*txPerHeight + i) counter := int64(blockN*txPerHeight + i)
tx := newTxCounter(counter, counter) tx := newTxCounter(counter, counter)
txBytes, err := codec.MarshalBinary(tx) txBytes, err := codec.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err) require.NoError(t, err)
res := app.DeliverTx(txBytes) res := app.DeliverTx(txBytes)
require.True(t, res.IsOK(), fmt.Sprintf("%v", res)) require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
@ -544,7 +544,7 @@ func TestMultiMsgDeliverTx(t *testing.T) {
{ {
app.BeginBlock(abci.RequestBeginBlock{}) app.BeginBlock(abci.RequestBeginBlock{})
tx := newTxCounter(0, 0, 1, 2) tx := newTxCounter(0, 0, 1, 2)
txBytes, err := codec.MarshalBinary(tx) txBytes, err := codec.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err) require.NoError(t, err)
res := app.DeliverTx(txBytes) res := app.DeliverTx(txBytes)
require.True(t, res.IsOK(), fmt.Sprintf("%v", res)) require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
@ -565,7 +565,7 @@ func TestMultiMsgDeliverTx(t *testing.T) {
tx := newTxCounter(1, 3) tx := newTxCounter(1, 3)
tx.Msgs = append(tx.Msgs, msgCounter2{0}) tx.Msgs = append(tx.Msgs, msgCounter2{0})
tx.Msgs = append(tx.Msgs, msgCounter2{1}) tx.Msgs = append(tx.Msgs, msgCounter2{1})
txBytes, err := codec.MarshalBinary(tx) txBytes, err := codec.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err) require.NoError(t, err)
res := app.DeliverTx(txBytes) res := app.DeliverTx(txBytes)
require.True(t, res.IsOK(), fmt.Sprintf("%v", res)) require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
@ -638,7 +638,7 @@ func TestSimulateTx(t *testing.T) {
require.Equal(t, gasConsumed, result.GasUsed) require.Equal(t, gasConsumed, result.GasUsed)
// simulate by calling Query with encoded tx // simulate by calling Query with encoded tx
txBytes, err := cdc.MarshalBinary(tx) txBytes, err := cdc.MarshalBinaryLengthPrefixed(tx)
require.Nil(t, err) require.Nil(t, err)
query := abci.RequestQuery{ query := abci.RequestQuery{
Path: "/app/simulate", Path: "/app/simulate",
@ -648,7 +648,7 @@ func TestSimulateTx(t *testing.T) {
require.True(t, queryResult.IsOK(), queryResult.Log) require.True(t, queryResult.IsOK(), queryResult.Log)
var res sdk.Result var res sdk.Result
codec.Cdc.MustUnmarshalBinary(queryResult.Value, &res) codec.Cdc.MustUnmarshalBinaryLengthPrefixed(queryResult.Value, &res)
require.Nil(t, err, "Result unmarshalling failed") require.Nil(t, err, "Result unmarshalling failed")
require.True(t, res.IsOK(), res.Log) require.True(t, res.IsOK(), res.Log)
require.Equal(t, gasConsumed, res.GasUsed, res.Log) require.Equal(t, gasConsumed, res.GasUsed, res.Log)
@ -729,7 +729,7 @@ func TestRunInvalidTransaction(t *testing.T) {
registerTestCodec(newCdc) registerTestCodec(newCdc)
newCdc.RegisterConcrete(&msgNoDecode{}, "cosmos-sdk/baseapp/msgNoDecode", nil) newCdc.RegisterConcrete(&msgNoDecode{}, "cosmos-sdk/baseapp/msgNoDecode", nil)
txBytes, err := newCdc.MarshalBinary(tx) txBytes, err := newCdc.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err) require.NoError(t, err)
res := app.DeliverTx(txBytes) res := app.DeliverTx(txBytes)
require.EqualValues(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeTxDecode), res.Code) require.EqualValues(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeTxDecode), res.Code)

View File

@ -121,8 +121,13 @@ func createVerifier() tmlite.Verifier {
fmt.Printf("Must specify these options: %s when --trust-node is false\n", errMsg.String()) fmt.Printf("Must specify these options: %s when --trust-node is false\n", errMsg.String())
os.Exit(1) os.Exit(1)
} }
node := rpcclient.NewHTTP(nodeURI, "/websocket") node := rpcclient.NewHTTP(nodeURI, "/websocket")
verifier, err := tmliteProxy.NewVerifier(chainID, filepath.Join(home, ".gaialite"), node, log.NewNopLogger()) cacheSize := 10 // TODO: determine appropriate cache size
verifier, err := tmliteProxy.NewVerifier(
chainID, filepath.Join(home, ".gaialite"),
node, log.NewNopLogger(), cacheSize,
)
if err != nil { if err != nil {
fmt.Printf("Create verifier failed: %s\n", err.Error()) fmt.Printf("Create verifier failed: %s\n", err.Error())

View File

@ -10,9 +10,9 @@ import (
"strings" "strings"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/store"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/merkle"
cmn "github.com/tendermint/tendermint/libs/common" cmn "github.com/tendermint/tendermint/libs/common"
tmliteErr "github.com/tendermint/tendermint/lite/errors" tmliteErr "github.com/tendermint/tendermint/lite/errors"
tmliteProxy "github.com/tendermint/tendermint/lite/proxy" tmliteProxy "github.com/tendermint/tendermint/lite/proxy"
@ -54,7 +54,7 @@ func (ctx CLIContext) QuerySubspace(subspace []byte, storeName string) (res []sd
return res, err return res, err
} }
ctx.Codec.MustUnmarshalBinary(resRaw, &res) ctx.Codec.MustUnmarshalBinaryLengthPrefixed(resRaw, &res)
return return
} }
@ -157,8 +157,8 @@ func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, err erro
} }
opts := rpcclient.ABCIQueryOptions{ opts := rpcclient.ABCIQueryOptions{
Height: ctx.Height, Height: ctx.Height,
Trusted: ctx.TrustNode, Prove: !ctx.TrustNode,
} }
result, err := node.ABCIQueryWithOptions(path, key, opts) result, err := node.ABCIQueryWithOptions(path, key, opts)
@ -198,7 +198,7 @@ func (ctx CLIContext) Verify(height int64) (tmtypes.SignedHeader, error) {
} }
// verifyProof perform response proof verification. // verifyProof perform response proof verification.
func (ctx CLIContext) verifyProof(_ string, resp abci.ResponseQuery) error { func (ctx CLIContext) verifyProof(queryPath string, resp abci.ResponseQuery) error {
if ctx.Verifier == nil { if ctx.Verifier == nil {
return fmt.Errorf("missing valid certifier to verify data from distrusted node") return fmt.Errorf("missing valid certifier to verify data from distrusted node")
} }
@ -209,25 +209,22 @@ func (ctx CLIContext) verifyProof(_ string, resp abci.ResponseQuery) error {
return err return err
} }
var multiStoreProof store.MultiStoreProof // TODO: Instead of reconstructing, stash on CLIContext field?
cdc := codec.New() prt := store.DefaultProofRuntime()
err = cdc.UnmarshalBinary(resp.Proof, &multiStoreProof) // TODO: Better convention for path?
storeName, err := parseQueryStorePath(queryPath)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to unmarshalBinary rangeProof") return err
} }
// verify the substore commit hash against trusted appHash kp := merkle.KeyPath{}
substoreCommitHash, err := store.VerifyMultiStoreCommitInfo( kp = kp.AppendKey([]byte(storeName), merkle.KeyEncodingURL)
multiStoreProof.StoreName, multiStoreProof.StoreInfos, commit.Header.AppHash, kp = kp.AppendKey(resp.Key, merkle.KeyEncodingURL)
)
if err != nil {
return errors.Wrap(err, "failed in verifying the proof against appHash")
}
err = store.VerifyRangeProof(resp.Key, resp.Value, substoreCommitHash, &multiStoreProof.RangeProof) err = prt.VerifyValue(resp.Proof, commit.Header.AppHash, kp.String(), resp.Value)
if err != nil { if err != nil {
return errors.Wrap(err, "failed in the range proof verification") return errors.Wrap(err, "failed to prove merkle proof")
} }
return nil return nil
@ -241,20 +238,40 @@ func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([
} }
// isQueryStoreWithProof expects a format like /<queryType>/<storeName>/<subpath> // isQueryStoreWithProof expects a format like /<queryType>/<storeName>/<subpath>
// queryType can be app or store. // queryType must be "store" and subpath must be "key" to require a proof.
func isQueryStoreWithProof(path string) bool { func isQueryStoreWithProof(path string) bool {
if !strings.HasPrefix(path, "/") { if !strings.HasPrefix(path, "/") {
return false return false
} }
paths := strings.SplitN(path[1:], "/", 3) paths := strings.SplitN(path[1:], "/", 3)
if len(paths) != 3 { switch {
case len(paths) != 3:
return false return false
} case paths[0] != "store":
return false
if store.RequireProof("/" + paths[2]) { case store.RequireProof("/" + paths[2]):
return true return true
} }
return false return false
} }
// parseQueryStorePath expects a format like /store/<storeName>/key.
func parseQueryStorePath(path string) (storeName string, err error) {
if !strings.HasPrefix(path, "/") {
return "", errors.New("expected path to start with /")
}
paths := strings.SplitN(path[1:], "/", 3)
switch {
case len(paths) != 3:
return "", errors.New("expected format like /store/<storeName>/key")
case paths[0] != "store":
return "", errors.New("expected format like /store/<storeName>/key")
case paths[2] != "key":
return "", errors.New("expected format like /store/<storeName>/key")
}
return paths[1], nil
}

View File

@ -158,11 +158,11 @@ func TestNodeStatus(t *testing.T) {
res, body := Request(t, port, "GET", "/node_info", nil) res, body := Request(t, port, "GET", "/node_info", nil)
require.Equal(t, http.StatusOK, res.StatusCode, body) require.Equal(t, http.StatusOK, res.StatusCode, body)
var nodeInfo p2p.NodeInfo var nodeInfo p2p.DefaultNodeInfo
err := cdc.UnmarshalJSON([]byte(body), &nodeInfo) err := cdc.UnmarshalJSON([]byte(body), &nodeInfo)
require.Nil(t, err, "Couldn't parse node info") require.Nil(t, err, "Couldn't parse node info")
require.NotEqual(t, p2p.NodeInfo{}, nodeInfo, "res: %v", res) require.NotEqual(t, p2p.DefaultNodeInfo{}, nodeInfo, "res: %v", res)
// syncing // syncing
res, body = Request(t, port, "GET", "/syncing", nil) res, body = Request(t, port, "GET", "/syncing", nil)

View File

@ -214,6 +214,7 @@ func InitializeTestLCD(
genTxs := []json.RawMessage{} genTxs := []json.RawMessage{}
// append any additional (non-proposing) validators // append any additional (non-proposing) validators
var accs []gapp.GenesisAccount
for i := 0; i < nValidators; i++ { for i := 0; i < nValidators; i++ {
operPrivKey := secp256k1.GenPrivKey() operPrivKey := secp256k1.GenPrivKey()
operAddr := operPrivKey.PubKey().Address() operAddr := operPrivKey.PubKey().Address()
@ -242,9 +243,17 @@ func InitializeTestLCD(
genTxs = append(genTxs, txBytes) genTxs = append(genTxs, txBytes)
valConsPubKeys = append(valConsPubKeys, pubKey) valConsPubKeys = append(valConsPubKeys, pubKey)
valOperAddrs = append(valOperAddrs, sdk.ValAddress(operAddr)) valOperAddrs = append(valOperAddrs, sdk.ValAddress(operAddr))
accAuth := auth.NewBaseAccountWithAddress(sdk.AccAddress(operAddr))
accAuth.Coins = sdk.Coins{sdk.NewInt64Coin("steak", 150)}
accs = append(accs, gapp.NewGenesisAccount(&accAuth))
} }
genesisState, err := gapp.GaiaAppGenState(cdc, genTxs) appGenState := gapp.NewDefaultGenesisState()
appGenState.Accounts = accs
genDoc.AppState, err = cdc.MarshalJSON(appGenState)
require.NoError(t, err)
genesisState, err := gapp.GaiaAppGenState(cdc, *genDoc, genTxs)
require.NoError(t, err) require.NoError(t, err)
// add some tokens to init accounts // add some tokens to init accounts

View File

@ -125,7 +125,7 @@ type Info struct {
func parseTx(cdc *codec.Codec, txBytes []byte) (sdk.Tx, error) { func parseTx(cdc *codec.Codec, txBytes []byte) (sdk.Tx, error) {
var tx auth.StdTx var tx auth.StdTx
err := cdc.UnmarshalBinary(txBytes, &tx) err := cdc.UnmarshalBinaryLengthPrefixed(txBytes, &tx)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -167,7 +167,7 @@ func adjustGasEstimate(estimate int64, adjustment float64) int64 {
func parseQueryResponse(cdc *amino.Codec, rawRes []byte) (int64, error) { func parseQueryResponse(cdc *amino.Codec, rawRes []byte) (int64, error) {
var simulationResult sdk.Result var simulationResult sdk.Result
if err := cdc.UnmarshalBinary(rawRes, &simulationResult); err != nil { if err := cdc.UnmarshalBinaryLengthPrefixed(rawRes, &simulationResult); err != nil {
return 0, err return 0, err
} }
return simulationResult.GasUsed, nil return simulationResult.GasUsed, nil

View File

@ -12,7 +12,7 @@ import (
func TestParseQueryResponse(t *testing.T) { func TestParseQueryResponse(t *testing.T) {
cdc := app.MakeCodec() cdc := app.MakeCodec()
sdkResBytes := cdc.MustMarshalBinary(sdk.Result{GasUsed: 10}) sdkResBytes := cdc.MustMarshalBinaryLengthPrefixed(sdk.Result{GasUsed: 10})
gas, err := parseQueryResponse(cdc, sdkResBytes) gas, err := parseQueryResponse(cdc, sdkResBytes)
assert.Equal(t, gas, int64(10)) assert.Equal(t, gas, int64(10))
assert.Nil(t, err) assert.Nil(t, err)
@ -28,7 +28,7 @@ func TestCalculateGas(t *testing.T) {
if wantErr { if wantErr {
return nil, errors.New("") return nil, errors.New("")
} }
return cdc.MustMarshalBinary(sdk.Result{GasUsed: gasUsed}), nil return cdc.MustMarshalBinaryLengthPrefixed(sdk.Result{GasUsed: gasUsed}), nil
} }
} }
type args struct { type args struct {

View File

@ -109,7 +109,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
app.cdc, app.cdc,
app.keyParams, app.tkeyParams, app.keyParams, app.tkeyParams,
) )
app.stakeKeeper = stake.NewKeeper( stakeKeeper := stake.NewKeeper(
app.cdc, app.cdc,
app.keyStake, app.tkeyStake, app.keyStake, app.tkeyStake,
app.bankKeeper, app.paramsKeeper.Subspace(stake.DefaultParamspace), app.bankKeeper, app.paramsKeeper.Subspace(stake.DefaultParamspace),
@ -117,30 +117,32 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
) )
app.mintKeeper = mint.NewKeeper(app.cdc, app.keyMint, app.mintKeeper = mint.NewKeeper(app.cdc, app.keyMint,
app.paramsKeeper.Subspace(mint.DefaultParamspace), app.paramsKeeper.Subspace(mint.DefaultParamspace),
app.stakeKeeper, app.feeCollectionKeeper, &stakeKeeper, app.feeCollectionKeeper,
) )
app.distrKeeper = distr.NewKeeper( app.distrKeeper = distr.NewKeeper(
app.cdc, app.cdc,
app.keyDistr, app.keyDistr,
app.paramsKeeper.Subspace(distr.DefaultParamspace), app.paramsKeeper.Subspace(distr.DefaultParamspace),
app.bankKeeper, app.stakeKeeper, app.feeCollectionKeeper, app.bankKeeper, &stakeKeeper, app.feeCollectionKeeper,
app.RegisterCodespace(stake.DefaultCodespace), app.RegisterCodespace(stake.DefaultCodespace),
) )
app.slashingKeeper = slashing.NewKeeper( app.slashingKeeper = slashing.NewKeeper(
app.cdc, app.cdc,
app.keySlashing, app.keySlashing,
app.stakeKeeper, app.paramsKeeper.Subspace(slashing.DefaultParamspace), &stakeKeeper, app.paramsKeeper.Subspace(slashing.DefaultParamspace),
app.RegisterCodespace(slashing.DefaultCodespace), app.RegisterCodespace(slashing.DefaultCodespace),
) )
app.govKeeper = gov.NewKeeper( app.govKeeper = gov.NewKeeper(
app.cdc, app.cdc,
app.keyGov, app.keyGov,
app.paramsKeeper, app.paramsKeeper.Subspace(gov.DefaultParamspace), app.bankKeeper, app.stakeKeeper, app.paramsKeeper, app.paramsKeeper.Subspace(gov.DefaultParamspace), app.bankKeeper, &stakeKeeper,
app.RegisterCodespace(gov.DefaultCodespace), app.RegisterCodespace(gov.DefaultCodespace),
) )
// register the staking hooks // register the staking hooks
app.stakeKeeper = app.stakeKeeper.WithHooks( // NOTE: stakeKeeper above are passed by reference,
// so that it can be modified like below:
app.stakeKeeper = *stakeKeeper.SetHooks(
NewHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks())) NewHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks()))
// register message routes // register message routes
@ -259,7 +261,7 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
if err != nil { if err != nil {
panic(err) panic(err)
} }
bz := app.cdc.MustMarshalBinary(tx) bz := app.cdc.MustMarshalBinaryLengthPrefixed(tx)
res := app.BaseApp.DeliverTx(bz) res := app.BaseApp.DeliverTx(bz)
if !res.IsOK() { if !res.IsOK() {
panic(res.Log) panic(res.Log)
@ -273,7 +275,8 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
// sanity check // sanity check
if len(req.Validators) > 0 { if len(req.Validators) > 0 {
if len(req.Validators) != len(validators) { if len(req.Validators) != len(validators) {
panic(fmt.Errorf("len(RequestInitChain.Validators) != len(validators) (%d != %d) ", len(req.Validators), len(validators))) panic(fmt.Errorf("len(RequestInitChain.Validators) != len(validators) (%d != %d)",
len(req.Validators), len(validators)))
} }
sort.Sort(abci.ValidatorUpdates(req.Validators)) sort.Sort(abci.ValidatorUpdates(req.Validators))
sort.Sort(abci.ValidatorUpdates(validators)) sort.Sort(abci.ValidatorUpdates(validators))

View File

@ -26,6 +26,7 @@ var (
// bonded tokens given to genesis validators/accounts // bonded tokens given to genesis validators/accounts
freeFermionVal = int64(100) freeFermionVal = int64(100)
freeFermionsAcc = sdk.NewInt(150) freeFermionsAcc = sdk.NewInt(150)
bondDenom = "steak"
) )
// State to Unmarshal // State to Unmarshal
@ -90,58 +91,60 @@ func GaiaAppInit() server.AppInit {
// Create the core parameters for genesis initialization for gaia // Create the core parameters for genesis initialization for gaia
// note that the pubkey input is this machines pubkey // note that the pubkey input is this machines pubkey
func GaiaAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (genesisState GenesisState, err error) { func GaiaAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) (
if len(appGenTxs) == 0 { genesisState GenesisState, err error) {
err = errors.New("must provide at least genesis transaction")
return if err = cdc.UnmarshalJSON(genDoc.AppState, &genesisState); err != nil {
return genesisState, err
} }
// start with the default staking genesis state // if there are no gen txs to be processed, return the default empty state
stakeData := stake.DefaultGenesisState() if len(appGenTxs) == 0 {
slashingData := slashing.DefaultGenesisState() return genesisState, errors.New("there must be at least one genesis tx")
}
// get genesis flag account information
genaccs := make([]GenesisAccount, len(appGenTxs))
stakeData := genesisState.StakeData
for i, genTx := range appGenTxs { for i, genTx := range appGenTxs {
var tx auth.StdTx var tx auth.StdTx
err = cdc.UnmarshalJSON(genTx, &tx) if err := cdc.UnmarshalJSON(genTx, &tx); err != nil {
if err != nil { return genesisState, err
return
} }
msgs := tx.GetMsgs() msgs := tx.GetMsgs()
if len(msgs) != 1 { if len(msgs) != 1 {
err = errors.New("must provide genesis StdTx with exactly 1 CreateValidator message") return genesisState, errors.New(
return "must provide genesis StdTx with exactly 1 CreateValidator message")
}
if _, ok := msgs[0].(stake.MsgCreateValidator); !ok {
return genesisState, fmt.Errorf(
"Genesis transaction %v does not contain a MsgCreateValidator", i)
} }
msg := msgs[0].(stake.MsgCreateValidator)
// create the genesis account, give'm few steaks and a buncha token with there name
genaccs[i] = genesisAccountFromMsgCreateValidator(msg, freeFermionsAcc)
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDecFromInt(freeFermionsAcc)) // increase the supply
} }
// create the final app state for _, acc := range genesisState.Accounts {
genesisState = GenesisState{ // create the genesis account, give'm few steaks and a buncha token with there name
Accounts: genaccs, for _, coin := range acc.Coins {
StakeData: stakeData, if coin.Denom == bondDenom {
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.
Add(sdk.NewDecFromInt(coin.Amount)) // increase the supply
}
}
}
genesisState.StakeData = stakeData
genesisState.GenTxs = appGenTxs
return genesisState, nil
}
// NewDefaultGenesisState generates the default state for gaia.
func NewDefaultGenesisState() GenesisState {
return GenesisState{
Accounts: nil,
StakeData: stake.DefaultGenesisState(),
MintData: mint.DefaultGenesisState(), MintData: mint.DefaultGenesisState(),
DistrData: distr.DefaultGenesisState(), DistrData: distr.DefaultGenesisState(),
GovData: gov.DefaultGenesisState(), GovData: gov.DefaultGenesisState(),
SlashingData: slashingData, SlashingData: slashing.DefaultGenesisState(),
GenTxs: appGenTxs, GenTxs: nil,
} }
return
}
func genesisAccountFromMsgCreateValidator(msg stake.MsgCreateValidator, amount sdk.Int) GenesisAccount {
accAuth := auth.NewBaseAccountWithAddress(sdk.AccAddress(msg.ValidatorAddr))
accAuth.Coins = []sdk.Coin{
{msg.Description.Moniker + "Token", sdk.NewInt(1000)},
{"steak", amount},
}
return NewGenesisAccount(&accAuth)
} }
// GaiaValidateGenesisState ensures that the genesis state obeys the expected invariants // GaiaValidateGenesisState ensures that the genesis state obeys the expected invariants
@ -175,27 +178,43 @@ func validateGenesisStateAccounts(accs []GenesisAccount) (err error) {
} }
// GaiaAppGenState but with JSON // GaiaAppGenState but with JSON
func GaiaAppGenStateJSON(cdc *codec.Codec, appGenTxs []json.RawMessage) (appState json.RawMessage, err error) { func GaiaAppGenStateJSON(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) (
appState json.RawMessage, err error) {
// create the final app state // create the final app state
genesisState, err := GaiaAppGenState(cdc, appGenTxs) genesisState, err := GaiaAppGenState(cdc, genDoc, appGenTxs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
appState, err = codec.MarshalJSONIndent(cdc, genesisState) return codec.MarshalJSONIndent(cdc, genesisState)
return
} }
// CollectStdTxs processes and validates application's genesis StdTxs and returns the list of validators, // CollectStdTxs processes and validates application's genesis StdTxs and returns
// appGenTxs, and persistent peers required to generate genesis.json. // the list of appGenTxs, and persistent peers required to generate genesis.json.
func CollectStdTxs(moniker string, genTxsDir string, cdc *codec.Codec) ( func CollectStdTxs(cdc *codec.Codec, moniker string, genTxsDir string, genDoc tmtypes.GenesisDoc) (
validators []tmtypes.GenesisValidator, appGenTxs []auth.StdTx, persistentPeers string, err error) { appGenTxs []auth.StdTx, persistentPeers string, err error) {
var fos []os.FileInfo var fos []os.FileInfo
fos, err = ioutil.ReadDir(genTxsDir) fos, err = ioutil.ReadDir(genTxsDir)
if err != nil { if err != nil {
return return appGenTxs, persistentPeers, err
} }
var addresses []string // prepare a map of all accounts in genesis state to then validate
// against the validators addresses
var appState GenesisState
if err := cdc.UnmarshalJSON(genDoc.AppState, &appState); err != nil {
return appGenTxs, persistentPeers, err
}
addrMap := make(map[string]GenesisAccount, len(appState.Accounts))
for i := 0; i < len(appState.Accounts); i++ {
acc := appState.Accounts[i]
strAddr := string(acc.Address)
addrMap[strAddr] = acc
}
// addresses and IPs (and port) validator server info
var addressesIPs []string
for _, fo := range fos { for _, fo := range fos {
filename := filepath.Join(genTxsDir, fo.Name()) filename := filepath.Join(genTxsDir, fo.Name())
if !fo.IsDir() && (filepath.Ext(filename) != ".json") { if !fo.IsDir() && (filepath.Ext(filename) != ".json") {
@ -204,48 +223,55 @@ func CollectStdTxs(moniker string, genTxsDir string, cdc *codec.Codec) (
// get the genStdTx // get the genStdTx
var jsonRawTx []byte var jsonRawTx []byte
jsonRawTx, err = ioutil.ReadFile(filename) if jsonRawTx, err = ioutil.ReadFile(filename); err != nil {
if err != nil { return appGenTxs, persistentPeers, err
return
} }
var genStdTx auth.StdTx var genStdTx auth.StdTx
err = cdc.UnmarshalJSON(jsonRawTx, &genStdTx) if err = cdc.UnmarshalJSON(jsonRawTx, &genStdTx); err != nil {
if err != nil { return appGenTxs, persistentPeers, err
return
} }
appGenTxs = append(appGenTxs, genStdTx) appGenTxs = append(appGenTxs, genStdTx)
nodeAddr := genStdTx.GetMemo() // the memo flag is used to store
if len(nodeAddr) == 0 { // the ip and node-id, for example this may be:
err = fmt.Errorf("couldn't find node's address in %s", fo.Name()) // "528fd3df22b31f4969b05652bfe8f0fe921321d5@192.168.2.37:26656"
return nodeAddrIP := genStdTx.GetMemo()
if len(nodeAddrIP) == 0 {
return appGenTxs, persistentPeers, fmt.Errorf(
"couldn't find node's address and IP in %s", fo.Name())
} }
// genesis transactions must be single-message
msgs := genStdTx.GetMsgs() msgs := genStdTx.GetMsgs()
if len(msgs) != 1 { if len(msgs) != 1 {
err = errors.New("each genesis transaction must provide a single genesis message")
return return appGenTxs, persistentPeers, errors.New(
"each genesis transaction must provide a single genesis message")
} }
// TODO: this could be decoupled from stake.MsgCreateValidator // validate the validator address and funds against the accounts in the state
// TODO: and we likely want to do it for real world Gaia
msg := msgs[0].(stake.MsgCreateValidator) msg := msgs[0].(stake.MsgCreateValidator)
validators = append(validators, tmtypes.GenesisValidator{ addr := string(sdk.AccAddress(msg.ValidatorAddr))
PubKey: msg.PubKey, acc, ok := addrMap[addr]
Power: freeFermionVal, if !ok {
Name: msg.Description.Moniker, return appGenTxs, persistentPeers, fmt.Errorf(
}) "account %v not in genesis.json: %+v", addr, addrMap)
}
if acc.Coins.AmountOf(msg.Delegation.Denom).LT(msg.Delegation.Amount) {
err = fmt.Errorf("insufficient fund for the delegation: %s < %s",
acc.Coins.AmountOf(msg.Delegation.Denom), msg.Delegation.Amount)
}
// exclude itself from persistent peers // exclude itself from persistent peers
if msg.Description.Moniker != moniker { if msg.Description.Moniker != moniker {
addresses = append(addresses, nodeAddr) addressesIPs = append(addressesIPs, nodeAddrIP)
} }
} }
sort.Strings(addresses) sort.Strings(addressesIPs)
persistentPeers = strings.Join(addresses, ",") persistentPeers = strings.Join(addressesIPs, ",")
return return appGenTxs, persistentPeers, nil
} }
func NewDefaultGenesisAccount(addr sdk.AccAddress) GenesisAccount { func NewDefaultGenesisAccount(addr sdk.AccAddress) GenesisAccount {

View File

@ -1,11 +1,13 @@
package app package app
import ( import (
"encoding/json"
"github.com/tendermint/tendermint/crypto/secp256k1"
tmtypes "github.com/tendermint/tendermint/types"
"testing" "testing"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/stake" "github.com/cosmos/cosmos-sdk/x/stake"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types" stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -27,7 +29,8 @@ var (
func makeGenesisState(t *testing.T, genTxs []auth.StdTx) GenesisState { func makeGenesisState(t *testing.T, genTxs []auth.StdTx) GenesisState {
// start with the default staking genesis state // start with the default staking genesis state
stakeData := stake.DefaultGenesisState() appState := NewDefaultGenesisState()
stakeData := appState.StakeData
genAccs := make([]GenesisAccount, len(genTxs)) genAccs := make([]GenesisAccount, len(genTxs))
for i, genTx := range genTxs { for i, genTx := range genTxs {
@ -35,17 +38,15 @@ func makeGenesisState(t *testing.T, genTxs []auth.StdTx) GenesisState {
require.Equal(t, 1, len(msgs)) require.Equal(t, 1, len(msgs))
msg := msgs[0].(stake.MsgCreateValidator) msg := msgs[0].(stake.MsgCreateValidator)
// get genesis flag account information acc := auth.NewBaseAccountWithAddress(sdk.AccAddress(msg.ValidatorAddr))
genAccs[i] = genesisAccountFromMsgCreateValidator(msg, freeFermionsAcc) acc.Coins = sdk.Coins{sdk.NewInt64Coin(bondDenom, 150)}
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDecFromInt(freeFermionsAcc)) // increase the supply genAccs[i] = NewGenesisAccount(&acc)
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDec(150)) // increase the supply
} }
// create the final app state // create the final app state
return GenesisState{ appState.Accounts = genAccs
Accounts: genAccs, return appState
StakeData: stakeData,
GovData: gov.DefaultGenesisState(),
}
} }
func TestToAccount(t *testing.T) { func TestToAccount(t *testing.T) {
@ -68,6 +69,19 @@ func TestGaiaAppGenTx(t *testing.T) {
func TestGaiaAppGenState(t *testing.T) { func TestGaiaAppGenState(t *testing.T) {
cdc := MakeCodec() cdc := MakeCodec()
_ = cdc _ = cdc
var genDoc tmtypes.GenesisDoc
// test unmarshalling error
_, err := GaiaAppGenState(cdc, genDoc, []json.RawMessage{})
require.Error(t, err)
appState := makeGenesisState(t, []auth.StdTx{})
genDoc.AppState, err = json.Marshal(appState)
require.NoError(t, err)
// test validation error
_, err = GaiaAppGenState(cdc, genDoc, []json.RawMessage{})
require.Error(t, err)
// TODO test must provide at least genesis transaction // TODO test must provide at least genesis transaction
// TODO test with both one and two genesis transactions: // TODO test with both one and two genesis transactions:
@ -77,7 +91,8 @@ func TestGaiaAppGenState(t *testing.T) {
func makeMsg(name string, pk crypto.PubKey) auth.StdTx { func makeMsg(name string, pk crypto.PubKey) auth.StdTx {
desc := stake.NewDescription(name, "", "", "") desc := stake.NewDescription(name, "", "", "")
comm := stakeTypes.CommissionMsg{} comm := stakeTypes.CommissionMsg{}
msg := stake.NewMsgCreateValidator(sdk.ValAddress(pk.Address()), pk, sdk.NewInt64Coin("steak", 50), desc, comm) msg := stake.NewMsgCreateValidator(sdk.ValAddress(pk.Address()), pk, sdk.NewInt64Coin(bondDenom,
50), desc, comm)
return auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, nil, "") return auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, nil, "")
} }
@ -106,3 +121,10 @@ func TestGaiaGenesisValidation(t *testing.T) {
err = GaiaValidateGenesisState(genesisState) err = GaiaValidateGenesisState(genesisState)
require.NotNil(t, err) require.NotNil(t, err)
} }
func TestNewDefaultGenesisAccount(t *testing.T) {
addr := secp256k1.GenPrivKeySecp256k1([]byte("")).PubKey().Address()
acc := NewDefaultGenesisAccount(sdk.AccAddress(addr))
require.Equal(t, sdk.NewInt(1000), acc.Coins.AmountOf("fooToken"))
require.Equal(t, sdk.NewInt(150), acc.Coins.AmountOf(bondDenom))
}

View File

@ -8,6 +8,7 @@ import (
"math/rand" "math/rand"
"os" "os"
"testing" "testing"
"time"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -50,42 +51,93 @@ func init() {
func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage { func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
var genesisAccounts []GenesisAccount var genesisAccounts []GenesisAccount
amt := int64(10000) amount := int64(r.Intn(1e6))
numInitiallyBonded := int64(r.Intn(250))
numAccs := int64(len(accs))
if numInitiallyBonded > numAccs {
numInitiallyBonded = numAccs
}
fmt.Printf("Selected randomly generated parameters for simulated genesis: {amount of steak per account: %v, initially bonded validators: %v}\n", amount, numInitiallyBonded)
// Randomly generate some genesis accounts // Randomly generate some genesis accounts
for _, acc := range accs { for _, acc := range accs {
coins := sdk.Coins{sdk.Coin{"steak", sdk.NewInt(amt)}} coins := sdk.Coins{sdk.Coin{"steak", sdk.NewInt(amount)}}
genesisAccounts = append(genesisAccounts, GenesisAccount{ genesisAccounts = append(genesisAccounts, GenesisAccount{
Address: acc.Address, Address: acc.Address,
Coins: coins, Coins: coins,
}) })
} }
// Default genesis state // Random genesis states
govGenesis := gov.DefaultGenesisState() govGenesis := gov.GenesisState{
stakeGenesis := stake.DefaultGenesisState() StartingProposalID: int64(r.Intn(100)),
slashingGenesis := slashing.DefaultGenesisState() DepositProcedure: gov.DepositProcedure{
MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", int64(r.Intn(1e3)))},
MaxDepositPeriod: time.Duration(r.Intn(2*172800)) * time.Second,
},
VotingProcedure: gov.VotingProcedure{
VotingPeriod: time.Duration(r.Intn(2*172800)) * time.Second,
},
TallyingProcedure: gov.TallyingProcedure{
Threshold: sdk.NewDecWithPrec(5, 1),
Veto: sdk.NewDecWithPrec(334, 3),
GovernancePenalty: sdk.NewDecWithPrec(1, 2),
},
}
fmt.Printf("Selected randomly generated governance parameters: %+v\n", govGenesis)
stakeGenesis := stake.GenesisState{
Pool: stake.InitialPool(),
Params: stake.Params{
UnbondingTime: time.Duration(r.Intn(60*60*24*3*2)) * time.Second,
MaxValidators: uint16(r.Intn(250)),
BondDenom: "steak",
},
}
fmt.Printf("Selected randomly generated staking parameters: %+v\n", stakeGenesis)
slashingGenesis := slashing.GenesisState{
Params: slashing.Params{
MaxEvidenceAge: stakeGenesis.Params.UnbondingTime,
DoubleSignUnbondDuration: time.Duration(r.Intn(60*60*24)) * time.Second,
SignedBlocksWindow: int64(r.Intn(1000)),
DowntimeUnbondDuration: time.Duration(r.Intn(86400)) * time.Second,
MinSignedPerWindow: sdk.NewDecWithPrec(int64(r.Intn(10)), 1),
SlashFractionDoubleSign: sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(50) + 1))),
SlashFractionDowntime: sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(200) + 1))),
},
}
fmt.Printf("Selected randomly generated slashing parameters: %+v\n", slashingGenesis)
mintGenesis := mint.GenesisState{
Minter: mint.Minter{
InflationLastTime: time.Unix(0, 0),
Inflation: sdk.NewDecWithPrec(int64(r.Intn(99)), 2),
},
Params: mint.Params{
MintDenom: "steak",
InflationRateChange: sdk.NewDecWithPrec(int64(r.Intn(99)), 2),
InflationMax: sdk.NewDecWithPrec(20, 2),
InflationMin: sdk.NewDecWithPrec(7, 2),
GoalBonded: sdk.NewDecWithPrec(67, 2),
},
}
fmt.Printf("Selected randomly generated minting parameters: %v\n", mintGenesis)
var validators []stake.Validator var validators []stake.Validator
var delegations []stake.Delegation var delegations []stake.Delegation
// XXX Try different numbers of initially bonded validators
numInitiallyBonded := int64(50)
valAddrs := make([]sdk.ValAddress, numInitiallyBonded) valAddrs := make([]sdk.ValAddress, numInitiallyBonded)
for i := 0; i < int(numInitiallyBonded); i++ { for i := 0; i < int(numInitiallyBonded); i++ {
valAddr := sdk.ValAddress(accs[i].Address) valAddr := sdk.ValAddress(accs[i].Address)
valAddrs[i] = valAddr valAddrs[i] = valAddr
validator := stake.NewValidator(valAddr, accs[i].PubKey, stake.Description{}) validator := stake.NewValidator(valAddr, accs[i].PubKey, stake.Description{})
validator.Tokens = sdk.NewDec(amt) validator.Tokens = sdk.NewDec(amount)
validator.DelegatorShares = sdk.NewDec(amt) validator.DelegatorShares = sdk.NewDec(amount)
delegation := stake.Delegation{accs[i].Address, valAddr, sdk.NewDec(amt), 0} delegation := stake.Delegation{accs[i].Address, valAddr, sdk.NewDec(amount), 0}
validators = append(validators, validator) validators = append(validators, validator)
delegations = append(delegations, delegation) delegations = append(delegations, delegation)
} }
stakeGenesis.Pool.LooseTokens = sdk.NewDec(amt*250 + (numInitiallyBonded * amt)) stakeGenesis.Pool.LooseTokens = sdk.NewDec((amount * numAccs) + (numInitiallyBonded * amount))
stakeGenesis.Validators = validators stakeGenesis.Validators = validators
stakeGenesis.Bonds = delegations stakeGenesis.Bonds = delegations
mintGenesis := mint.DefaultGenesisState()
genesis := GenesisState{ genesis := GenesisState{
Accounts: genesisAccounts, Accounts: genesisAccounts,

View File

@ -5,9 +5,11 @@ package clitest
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/tendermint/tendermint/types"
"io/ioutil" "io/ioutil"
"os" "os"
"path" "path"
"path/filepath"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -207,7 +209,7 @@ func TestGaiaCLIGasAuto(t *testing.T) {
func TestGaiaCLICreateValidator(t *testing.T) { func TestGaiaCLICreateValidator(t *testing.T) {
chainID, servAddr, port := initializeFixtures(t) chainID, servAddr, port := initializeFixtures(t)
flags := fmt.Sprintf("--home=%s --node=%v --chain-id=%v", gaiacliHome, servAddr, chainID) flags := fmt.Sprintf("--home=%s --chain-id=%v --node=%s", gaiacliHome, chainID, servAddr)
// start gaiad server // start gaiad server
proc := tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --home=%s --rpc.laddr=%v", gaiadHome, servAddr)) proc := tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --home=%s --rpc.laddr=%v", gaiadHome, servAddr))
@ -544,7 +546,7 @@ func TestGaiaCLIConfig(t *testing.T) {
servAddr, port, err := server.FreeTCPAddr() servAddr, port, err := server.FreeTCPAddr()
require.NoError(t, err) require.NoError(t, err)
node := fmt.Sprintf("%s:%s", servAddr, port) node := fmt.Sprintf("%s:%s", servAddr, port)
chainID := executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) chainID := executeInit(t, fmt.Sprintf("gaiad init -o --moniker=foo --home=%s", gaiadHome))
executeWrite(t, fmt.Sprintf("gaiacli --home=%s config", gaiadHome), gaiacliHome, node, "y") executeWrite(t, fmt.Sprintf("gaiacli --home=%s config", gaiadHome), gaiacliHome, node, "y")
config, err := ioutil.ReadFile(path.Join(gaiacliHome, "config", "config.toml")) config, err := ioutil.ReadFile(path.Join(gaiacliHome, "config", "config.toml"))
require.NoError(t, err) require.NoError(t, err)
@ -594,12 +596,27 @@ func initializeFixtures(t *testing.T) (chainID, servAddr, port string) {
tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe-reset-all", gaiadHome), "") tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe-reset-all", gaiadHome), "")
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass)
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass)
executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s foo", gaiacliHome), app.DefaultKeyPass)
chainID = executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome))
executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), app.DefaultKeyPass) executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), app.DefaultKeyPass)
fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf(
"gaiacli keys show foo --output=json --home=%s", gaiacliHome))
chainID = executeInit(t, fmt.Sprintf("gaiad init -o --moniker=foo --home=%s", gaiadHome))
genFile := filepath.Join(gaiadHome, "config", "genesis.json")
genDoc := readGenesisFile(t, genFile)
var appState app.GenesisState
err := codec.Cdc.UnmarshalJSON(genDoc.AppState, &appState)
require.NoError(t, err)
appState.Accounts = []app.GenesisAccount{app.NewDefaultGenesisAccount(fooAddr)}
appStateJSON, err := codec.Cdc.MarshalJSON(appState)
require.NoError(t, err)
genDoc.AppState = appStateJSON
genDoc.SaveAs(genFile)
executeWrite(t, fmt.Sprintf(
"gaiad gentx --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome),
app.DefaultKeyPass)
executeWrite(t, fmt.Sprintf("gaiad collect-gentxs --home=%s", gaiadHome), app.DefaultKeyPass)
// get a free port, also setup some common flags // get a free port, also setup some common flags
servAddr, port, err := server.FreeTCPAddr() servAddr, port, err = server.FreeTCPAddr()
require.NoError(t, err) require.NoError(t, err)
return return
} }
@ -618,6 +635,18 @@ func writeToNewTempFile(t *testing.T, s string) *os.File {
return fp return fp
} }
func readGenesisFile(t *testing.T, genFile string) types.GenesisDoc {
var genDoc types.GenesisDoc
fp, err := os.Open(genFile)
require.NoError(t, err)
fileContents, err := ioutil.ReadAll(fp)
require.NoError(t, err)
defer fp.Close()
err = codec.Cdc.UnmarshalJSON(fileContents, &genDoc)
require.NoError(t, err)
return genDoc
}
//___________________________________________________________________________________ //___________________________________________________________________________________
// executors // executors

View File

@ -39,7 +39,8 @@ func main() {
} }
appInit := app.GaiaAppInit() appInit := app.GaiaAppInit()
rootCmd.AddCommand(gaiaInit.InitCmd(ctx, cdc, appInit)) rootCmd.AddCommand(gaiaInit.InitCmd(ctx, cdc, appInit))
rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, appInit)) rootCmd.AddCommand(gaiaInit.CollectGenTxsCmd(ctx, cdc))
rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, server.AppInit{}))
rootCmd.AddCommand(gaiaInit.GenTxCmd(ctx, cdc)) rootCmd.AddCommand(gaiaInit.GenTxCmd(ctx, cdc))
server.AddCommands(ctx, cdc, rootCmd, appInit, server.AddCommands(ctx, cdc, rootCmd, appInit,

View File

@ -220,7 +220,7 @@ func runTxCmd(cmd *cobra.Command, args []string) error {
var tx = auth.StdTx{} var tx = auth.StdTx{}
cdc := gaia.MakeCodec() cdc := gaia.MakeCodec()
err = cdc.UnmarshalBinary(txBytes, &tx) err = cdc.UnmarshalBinaryLengthPrefixed(txBytes, &tx)
if err != nil { if err != nil {
return err return err
} }

119
cmd/gaia/init/collect.go Normal file
View File

@ -0,0 +1,119 @@
package init
import (
"encoding/json"
"io/ioutil"
"path/filepath"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/tendermint/go-amino"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/libs/cli"
"github.com/tendermint/tendermint/types"
)
type initConfig struct {
ChainID string
GenTxsDir string
Name string
NodeID string
ValPubKey crypto.PubKey
}
// nolint
func CollectGenTxsCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "collect-gentxs",
Short: "Collect genesis txs and output a genesis.json file",
RunE: func(_ *cobra.Command, _ []string) error {
config := ctx.Config
config.SetRoot(viper.GetString(cli.HomeFlag))
name := viper.GetString(client.FlagName)
nodeID, valPubKey, err := InitializeNodeValidatorFiles(config)
if err != nil {
return err
}
genDoc, err := loadGenesisDoc(cdc, config.GenesisFile())
if err != nil {
return err
}
toPrint := printInfo{
Moniker: config.Moniker,
ChainID: genDoc.ChainID,
NodeID: nodeID,
}
initCfg := initConfig{
ChainID: genDoc.ChainID,
GenTxsDir: filepath.Join(config.RootDir, "config", "gentx"),
Name: name,
NodeID: nodeID,
ValPubKey: valPubKey,
}
appMessage, err := genAppStateFromConfig(cdc, config, initCfg, genDoc)
if err != nil {
return err
}
toPrint.AppMessage = appMessage
// print out some key information
return displayInfo(cdc, toPrint)
},
}
cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory")
return cmd
}
func genAppStateFromConfig(cdc *codec.Codec, config *cfg.Config, initCfg initConfig,
genDoc types.GenesisDoc) (appState json.RawMessage, err error) {
genFile := config.GenesisFile()
// process genesis transactions, else create default genesis.json
var appGenTxs []auth.StdTx
var persistentPeers string
var genTxs []json.RawMessage
var jsonRawTx json.RawMessage
appGenTxs, persistentPeers, err = app.CollectStdTxs(
cdc, config.Moniker, initCfg.GenTxsDir, genDoc)
if err != nil {
return
}
genTxs = make([]json.RawMessage, len(appGenTxs))
config.P2P.PersistentPeers = persistentPeers
for i, stdTx := range appGenTxs {
jsonRawTx, err = cdc.MarshalJSON(stdTx)
if err != nil {
return
}
genTxs[i] = jsonRawTx
}
cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config)
appState, err = app.GaiaAppGenStateJSON(cdc, genDoc, genTxs)
if err != nil {
return
}
err = WriteGenesisFile(genFile, initCfg.ChainID, nil, appState)
return
}
func loadGenesisDoc(cdc *amino.Codec, genFile string) (genDoc types.GenesisDoc, err error) {
genContents, err := ioutil.ReadFile(genFile)
if err != nil {
return
}
err = cdc.UnmarshalJSON(genContents, &genDoc)
return
}

View File

@ -55,9 +55,20 @@ following delegation and commission default parameters:
if err != nil { if err != nil {
return err return err
} }
genDoc, err := loadGenesisDoc(cdc, config.GenesisFile())
if 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)
if err != nil {
return err
}
}
// Run gaiad tx create-validator // Run gaiad tx create-validator
prepareFlagsForTxCreateValidator(config, nodeID, ip, valPubKey) prepareFlagsForTxCreateValidator(config, nodeID, ip, genDoc.ChainID, valPubKey)
createValidatorCmd := cli.GetCmdCreateValidator(cdc) createValidatorCmd := cli.GetCmdCreateValidator(cdc)
w, err := ioutil.TempFile("", "gentx") w, err := ioutil.TempFile("", "gentx")
@ -82,28 +93,41 @@ following delegation and commission default parameters:
}, },
} }
cmd.Flags().String(tmcli.HomeFlag, app.DefaultNodeHome, "node's home directory")
cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory") cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory")
cmd.Flags().String(client.FlagChainID, "", "genesis file chain-id")
cmd.Flags().String(client.FlagName, "", "name of private key with which to sign the gentx") cmd.Flags().String(client.FlagName, "", "name of private key with which to sign the gentx")
cmd.Flags().AddFlagSet(cli.FsCommissionCreate)
cmd.Flags().AddFlagSet(cli.FsAmount)
cmd.Flags().AddFlagSet(cli.FsPk)
cmd.MarkFlagRequired(client.FlagName) cmd.MarkFlagRequired(client.FlagName)
return cmd return cmd
} }
func prepareFlagsForTxCreateValidator(config *cfg.Config, nodeID, ip string, valPubKey crypto.PubKey) { func prepareFlagsForTxCreateValidator(config *cfg.Config, nodeID, ip, chainID string,
viper.Set(tmcli.HomeFlag, viper.GetString(flagClientHome)) // --home valPubKey crypto.PubKey) {
viper.Set(tmcli.HomeFlag, viper.GetString(flagClientHome)) // --home
viper.Set(client.FlagChainID, chainID)
viper.Set(client.FlagFrom, viper.GetString(client.FlagName)) // --from viper.Set(client.FlagFrom, viper.GetString(client.FlagName)) // --from
viper.Set(cli.FlagNodeID, nodeID) // --node-id viper.Set(cli.FlagNodeID, nodeID) // --node-id
viper.Set(cli.FlagIP, ip) // --ip viper.Set(cli.FlagIP, ip) // --ip
viper.Set(cli.FlagPubKey, sdk.MustBech32ifyConsPub(valPubKey)) // --pubkey viper.Set(cli.FlagPubKey, sdk.MustBech32ifyConsPub(valPubKey)) // --pubkey
viper.Set(cli.FlagAmount, defaultAmount) // --amount viper.Set(cli.FlagGenesisFormat, true) // --genesis-format
viper.Set(cli.FlagCommissionRate, defaultCommissionRate) viper.Set(cli.FlagMoniker, config.Moniker) // --moniker
viper.Set(cli.FlagCommissionMaxRate, defaultCommissionMaxRate)
viper.Set(cli.FlagCommissionMaxChangeRate, defaultCommissionMaxChangeRate)
viper.Set(cli.FlagGenesisFormat, true) // --genesis-format
viper.Set(cli.FlagMoniker, config.Moniker) // --moniker
if config.Moniker == "" { if config.Moniker == "" {
viper.Set(cli.FlagMoniker, viper.GetString(client.FlagName)) viper.Set(cli.FlagMoniker, viper.GetString(client.FlagName))
} }
if viper.GetString(cli.FlagAmount) == "" {
viper.Set(cli.FlagAmount, defaultAmount)
}
if viper.GetString(cli.FlagCommissionRate) == "" {
viper.Set(cli.FlagCommissionRate, defaultCommissionRate)
}
if viper.GetString(cli.FlagCommissionMaxRate) == "" {
viper.Set(cli.FlagCommissionMaxRate, defaultCommissionMaxRate)
}
if viper.GetString(cli.FlagCommissionMaxChangeRate) == "" {
viper.Set(cli.FlagCommissionMaxChangeRate, defaultCommissionMaxChangeRate)
}
} }
func prepareFlagsForTxSign() { func prepareFlagsForTxSign() {

View File

@ -2,24 +2,19 @@ package init
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
"github.com/cosmos/cosmos-sdk/x/auth"
authtx "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/cosmos/cosmos-sdk/x/stake"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/privval" "github.com/tendermint/tendermint/privval"
"os" "os"
"path/filepath" "path/filepath"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
cfg "github.com/tendermint/tendermint/config" cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/libs/cli" "github.com/tendermint/tendermint/libs/cli"
"github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/libs/common"
"github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/p2p"
@ -27,26 +22,11 @@ import (
) )
const ( const (
flagWithTxs = "with-txs" flagOverwrite = "overwrite"
flagOverwrite = "overwrite" flagClientHome = "home-client"
flagClientHome = "home-client" flagMoniker = "moniker"
flagOverwriteKey = "overwrite-key"
flagSkipGenesis = "skip-genesis"
flagMoniker = "moniker"
) )
type initConfig struct {
ChainID string
GenTxsDir string
Name string
NodeID string
ClientHome string
WithTxs bool
Overwrite bool
OverwriteKey bool
ValPubKey crypto.PubKey
}
type printInfo struct { type printInfo struct {
Moniker string `json:"moniker"` Moniker string `json:"moniker"`
ChainID string `json:"chain_id"` ChainID string `json:"chain_id"`
@ -70,22 +50,16 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "init", Use: "init",
Short: "Initialize private validator, p2p, genesis, and application configuration files", Short: "Initialize private validator, p2p, genesis, and application configuration files",
Long: `Initialize validators's and node's configuration files. Long: `Initialize validators's and node's configuration files.`,
Args: cobra.NoArgs,
Note that only node's configuration files will be written if the flag --skip-genesis is
enabled, and the genesis file will not be generated.
`,
Args: cobra.NoArgs,
RunE: func(_ *cobra.Command, _ []string) error { RunE: func(_ *cobra.Command, _ []string) error {
config := ctx.Config config := ctx.Config
config.SetRoot(viper.GetString(cli.HomeFlag)) config.SetRoot(viper.GetString(cli.HomeFlag))
name := viper.GetString(client.FlagName)
chainID := viper.GetString(client.FlagChainID) chainID := viper.GetString(client.FlagChainID)
if chainID == "" { if chainID == "" {
chainID = fmt.Sprintf("test-chain-%v", common.RandStr(6)) chainID = fmt.Sprintf("test-chain-%v", common.RandStr(6))
} }
nodeID, valPubKey, err := InitializeNodeValidatorFiles(config) nodeID, _, err := InitializeNodeValidatorFiles(config)
if err != nil { if err != nil {
return err return err
} }
@ -93,37 +67,26 @@ enabled, and the genesis file will not be generated.
if viper.GetString(flagMoniker) != "" { if viper.GetString(flagMoniker) != "" {
config.Moniker = viper.GetString(flagMoniker) config.Moniker = viper.GetString(flagMoniker)
} }
if config.Moniker == "" && name != "" {
config.Moniker = name
}
toPrint := printInfo{
ChainID: chainID,
Moniker: config.Moniker,
NodeID: nodeID,
}
if viper.GetBool(flagSkipGenesis) {
cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config)
return displayInfo(cdc, toPrint)
}
initCfg := initConfig{ var appState json.RawMessage
ChainID: chainID, genFile := config.GenesisFile()
GenTxsDir: filepath.Join(config.RootDir, "config", "gentx"), if appState, err = initializeEmptyGenesis(cdc, genFile, chainID,
Name: name, viper.GetBool(flagOverwrite)); err != nil {
NodeID: nodeID, return err
ClientHome: viper.GetString(flagClientHome),
WithTxs: viper.GetBool(flagWithTxs),
Overwrite: viper.GetBool(flagOverwrite),
OverwriteKey: viper.GetBool(flagOverwriteKey),
ValPubKey: valPubKey,
} }
appMessage, err := initWithConfig(cdc, config, initCfg) if err = WriteGenesisFile(genFile, chainID, nil, appState); err != nil {
// print out some key information
if err != nil {
return err return err
} }
toPrint.AppMessage = appMessage toPrint := printInfo{
ChainID: chainID,
Moniker: config.Moniker,
NodeID: nodeID,
AppMessage: appState,
}
cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config)
return displayInfo(cdc, toPrint) return displayInfo(cdc, toPrint)
}, },
} }
@ -131,12 +94,7 @@ enabled, and the genesis file will not be generated.
cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory") cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory")
cmd.Flags().BoolP(flagOverwrite, "o", false, "overwrite the genesis.json file") cmd.Flags().BoolP(flagOverwrite, "o", false, "overwrite the genesis.json file")
cmd.Flags().String(client.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") cmd.Flags().String(client.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
cmd.Flags().Bool(flagWithTxs, false, "apply existing genesis transactions from [--home]/config/gentx/") cmd.Flags().String(flagMoniker, "", "set the validator's moniker")
cmd.Flags().String(client.FlagName, "", "name of private key with which to sign the gentx")
cmd.Flags().String(flagMoniker, "", "overrides --name flag and set the validator's moniker to a different value; ignored if it runs without the --with-txs flag")
cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory")
cmd.Flags().Bool(flagOverwriteKey, false, "overwrite client's key")
cmd.Flags().Bool(flagSkipGenesis, false, "do not create genesis.json")
return cmd return cmd
} }
@ -151,105 +109,6 @@ func InitializeNodeValidatorFiles(config *cfg.Config) (nodeID string, valPubKey
return return
} }
func initWithConfig(cdc *codec.Codec, config *cfg.Config, initCfg initConfig) (
appMessage json.RawMessage, err error) {
genFile := config.GenesisFile()
if !initCfg.Overwrite && common.FileExists(genFile) {
err = fmt.Errorf("genesis.json file already exists: %v", genFile)
return
}
// process genesis transactions, else create default genesis.json
var appGenTxs []auth.StdTx
var persistentPeers string
var genTxs []json.RawMessage
var appState json.RawMessage
var jsonRawTx json.RawMessage
chainID := initCfg.ChainID
if initCfg.WithTxs {
_, appGenTxs, persistentPeers, err = app.CollectStdTxs(config.Moniker, initCfg.GenTxsDir, cdc)
if err != nil {
return
}
genTxs = make([]json.RawMessage, len(appGenTxs))
config.P2P.PersistentPeers = persistentPeers
for i, stdTx := range appGenTxs {
jsonRawTx, err = cdc.MarshalJSON(stdTx)
if err != nil {
return
}
genTxs[i] = jsonRawTx
}
} else {
var ip, keyPass, secret string
var addr sdk.AccAddress
var signedTx auth.StdTx
if initCfg.Name == "" {
err = errors.New("must specify validator's moniker (--name)")
return
}
config.Moniker = initCfg.Name
ip, err = server.ExternalIP()
if err != nil {
return
}
memo := fmt.Sprintf("%s@%s:26656", initCfg.NodeID, ip)
buf := client.BufferStdin()
prompt := fmt.Sprintf("Password for account %q (default: %q):", initCfg.Name, app.DefaultKeyPass)
keyPass, err = client.GetPassword(prompt, buf)
if err != nil && keyPass != "" {
// An error was returned that either failed to read the password from
// STDIN or the given password is not empty but failed to meet minimum
// length requirements.
return
}
if keyPass == "" {
keyPass = app.DefaultKeyPass
}
addr, secret, err = server.GenerateSaveCoinKey(initCfg.ClientHome, initCfg.Name, keyPass, initCfg.OverwriteKey)
if err != nil {
return
}
appMessage, err = json.Marshal(map[string]string{"secret": secret})
if err != nil {
return
}
msg := stake.NewMsgCreateValidator(
sdk.ValAddress(addr),
initCfg.ValPubKey,
sdk.NewInt64Coin("steak", 100),
stake.NewDescription(config.Moniker, "", "", ""),
stake.NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
)
txBldr := authtx.NewTxBuilderFromCLI().WithCodec(cdc).WithMemo(memo).WithChainID(chainID)
signedTx, err = txBldr.SignStdTx(
initCfg.Name, keyPass, auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, []auth.StdSignature{}, memo), false,
)
if err != nil {
return
}
jsonRawTx, err = cdc.MarshalJSON(signedTx)
if err != nil {
return
}
genTxs = []json.RawMessage{jsonRawTx}
}
cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config)
appState, err = app.GaiaAppGenStateJSON(cdc, genTxs)
if err != nil {
return
}
err = WriteGenesisFile(genFile, chainID, nil, appState)
return
}
// WriteGenesisFile creates and writes the genesis configuration to disk. An // WriteGenesisFile creates and writes the genesis configuration to disk. An
// error is returned if building or writing the configuration to file fails. // error is returned if building or writing the configuration to file fails.
// nolint: unparam // nolint: unparam
@ -279,3 +138,13 @@ func ReadOrCreatePrivValidator(privValFile string) crypto.PubKey {
} }
return privValidator.GetPubKey() return privValidator.GetPubKey()
} }
func initializeEmptyGenesis(cdc *codec.Codec, genFile string, chainID string,
overwrite bool) (appState json.RawMessage, err error) {
if !overwrite && common.FileExists(genFile) {
err = fmt.Errorf("genesis.json file already exists: %v", genFile)
return
}
return codec.MarshalJSONIndent(cdc, app.NewDefaultGenesisState())
}

View File

@ -42,7 +42,6 @@ func setupClientHome(t *testing.T) func() {
clientDir, err := ioutil.TempDir("", "mock-sdk-cmd") clientDir, err := ioutil.TempDir("", "mock-sdk-cmd")
require.Nil(t, err) require.Nil(t, err)
viper.Set(flagClientHome, clientDir) viper.Set(flagClientHome, clientDir)
viper.Set(flagOverwriteKey, true)
return func() { return func() {
if err := os.RemoveAll(clientDir); err != nil { if err := os.RemoveAll(clientDir); err != nil {
// TODO: Handle with #870 // TODO: Handle with #870

View File

@ -10,6 +10,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth"
authtx "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" authtx "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/cosmos/cosmos-sdk/x/stake" "github.com/cosmos/cosmos-sdk/x/stake"
"github.com/tendermint/tendermint/types"
"net" "net"
"os" "os"
"path/filepath" "path/filepath"
@ -35,7 +36,9 @@ var (
const nodeDirPerm = 0755 const nodeDirPerm = 0755
// get cmd to initialize all files for tendermint testnet and application // 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,
appInit server.AppInit) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "testnet", Use: "testnet",
Short: "Initialize files for a Gaiad testnet", Short: "Initialize files for a Gaiad testnet",
@ -50,7 +53,7 @@ Example:
`, `,
RunE: func(_ *cobra.Command, _ []string) error { RunE: func(_ *cobra.Command, _ []string) error {
config := ctx.Config config := ctx.Config
return testnetWithConfig(config, cdc, appInit) return testnetWithConfig(config, cdc)
}, },
} }
cmd.Flags().Int(nValidators, 4, cmd.Flags().Int(nValidators, 4,
@ -69,7 +72,7 @@ Example:
return cmd return cmd
} }
func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit server.AppInit) error { func testnetWithConfig(config *cfg.Config, cdc *codec.Codec) error {
outDir := viper.GetString(outputDir) outDir := viper.GetString(outputDir)
numValidators := viper.GetInt(nValidators) numValidators := viper.GetInt(nValidators)
@ -80,6 +83,8 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit server.AppI
valPubKeys := make([]crypto.PubKey, numValidators) valPubKeys := make([]crypto.PubKey, numValidators)
// Generate private key, node ID, initial transaction // Generate private key, node ID, initial transaction
var accs []app.GenesisAccount
var genFiles []string
for i := 0; i < numValidators; i++ { for i := 0; i < numValidators; i++ {
nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i) nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i)
nodeDaemonHomeName := viper.GetString(nodeDaemonHome) nodeDaemonHomeName := viper.GetString(nodeDaemonHome)
@ -115,8 +120,12 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit server.AppI
} }
memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip) memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip)
// write genesis
genFiles = append(genFiles, config.GenesisFile())
buf := client.BufferStdin() buf := client.BufferStdin()
prompt := fmt.Sprintf("Password for account '%s' (default %s):", nodeDirName, app.DefaultKeyPass) prompt := fmt.Sprintf(
"Password for account '%s' (default %s):", nodeDirName, app.DefaultKeyPass)
keyPass, err := client.GetPassword(prompt, buf) keyPass, err := client.GetPassword(prompt, buf)
if err != nil && keyPass != "" { if err != nil && keyPass != "" {
// An error was returned that either failed to read the password from // An error was returned that either failed to read the password from
@ -138,12 +147,20 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit server.AppI
if err != nil { if err != nil {
return err return err
} }
// Save private key seed words // save private key seed words
err = writeFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, cliPrint) err = writeFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, cliPrint)
if err != nil { if err != nil {
return err return err
} }
accs = append(accs, app.GenesisAccount{
Address: addr,
Coins: sdk.Coins{
sdk.NewInt64Coin(fmt.Sprintf("%sToken", nodeDirName), 1000),
sdk.NewInt64Coin("steak", 150),
},
})
msg := stake.NewMsgCreateValidator( msg := stake.NewMsgCreateValidator(
sdk.ValAddress(addr), sdk.ValAddress(addr),
valPubKeys[i], valPubKeys[i],
@ -173,8 +190,27 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit server.AppI
} }
} }
for i := 0; i < numValidators; i++ { // Generate empty genesis.json
appGenState := app.NewDefaultGenesisState()
appGenState.Accounts = accs
appGenStateJSON, err := codec.MarshalJSONIndent(cdc, appGenState)
if err != nil {
return err
}
genDoc := types.GenesisDoc{
ChainID: chainID,
AppState: appGenStateJSON,
Validators: nil,
}
// Save all genesis.json files
for i := 0; i < numValidators; i++ {
if err := genDoc.SaveAs(genFiles[i]); err != nil {
return err
}
}
for i := 0; i < numValidators; i++ {
nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i) nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i)
nodeDaemonHomeName := viper.GetString(nodeDaemonHome) nodeDaemonHomeName := viper.GetString(nodeDaemonHome)
nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName) nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName)
@ -186,16 +222,17 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit server.AppI
nodeID, valPubKey := nodeIDs[i], valPubKeys[i] nodeID, valPubKey := nodeIDs[i], valPubKeys[i]
// Run `init` and generate genesis.json and config.toml // Run `init` and generate genesis.json and config.toml
initCfg := initConfig{ initCfg := initConfig{
ChainID: chainID, ChainID: chainID,
GenTxsDir: gentxsDir, GenTxsDir: gentxsDir,
Name: moniker, Name: moniker,
WithTxs: true, NodeID: nodeID,
Overwrite: true, ValPubKey: valPubKey,
OverwriteKey: false,
NodeID: nodeID,
ValPubKey: valPubKey,
} }
if _, err := initWithConfig(cdc, config, initCfg); err != nil { genDoc, err := loadGenesisDoc(cdc, config.GenesisFile())
if err != nil {
return err
}
if _, err := genAppStateFromConfig(cdc, config, initCfg, genDoc); err != nil {
return err return err
} }
} }

View File

@ -273,7 +273,7 @@ func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig []byte, pub t
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
cdc.MustUnmarshalBinary([]byte(signed), sig) cdc.MustUnmarshalBinaryLengthPrefixed([]byte(signed), sig)
return sig, linfo.GetPubKey(), nil return sig, linfo.GetPubKey(), nil
} }
sig, err = priv.Sign(msg) sig, err = priv.Sign(msg)

View File

@ -182,11 +182,11 @@ func (i offlineInfo) GetAddress() types.AccAddress {
// encoding info // encoding info
func writeInfo(i Info) []byte { func writeInfo(i Info) []byte {
return cdc.MustMarshalBinary(i) return cdc.MustMarshalBinaryLengthPrefixed(i)
} }
// decoding info // decoding info
func readInfo(bz []byte) (info Info, err error) { func readInfo(bz []byte) (info Info, err error) {
err = cdc.UnmarshalBinary(bz, &info) err = cdc.UnmarshalBinaryLengthPrefixed(bz, &info)
return return
} }

View File

@ -178,7 +178,7 @@ func (tx app2Tx) GetMsgs() []sdk.Msg {
func tx2Decoder(cdc *codec.Codec) sdk.TxDecoder { func tx2Decoder(cdc *codec.Codec) sdk.TxDecoder {
return func(txBytes []byte) (sdk.Tx, sdk.Error) { return func(txBytes []byte) (sdk.Tx, sdk.Error) {
var tx app2Tx var tx app2Tx
err := cdc.UnmarshalBinary(txBytes, &tx) err := cdc.UnmarshalBinaryLengthPrefixed(txBytes, &tx)
if err != nil { if err != nil {
return nil, sdk.ErrTxDecode(err.Error()) return nil, sdk.ErrTxDecode(err.Error())
} }

View File

@ -201,7 +201,7 @@ func (tx app2Tx) GetSignature() []byte {
func tx2Decoder(cdc *codec.Codec) sdk.TxDecoder { func tx2Decoder(cdc *codec.Codec) sdk.TxDecoder {
return func(txBytes []byte) (sdk.Tx, sdk.Error) { return func(txBytes []byte) (sdk.Tx, sdk.Error) {
var tx app2Tx var tx app2Tx
err := cdc.UnmarshalBinary(txBytes, &tx) err := cdc.UnmarshalBinaryLengthPrefixed(txBytes, &tx)
if err != nil { if err != nil {
return nil, sdk.ErrTxDecode(err.Error()) return nil, sdk.ErrTxDecode(err.Error())
} }

View File

@ -39,7 +39,7 @@ func TestEncoding(t *testing.T) {
cdc := NewCodec() cdc := NewCodec()
testTxDecoder := tx2Decoder(cdc) testTxDecoder := tx2Decoder(cdc)
encodedSendTx, err := cdc.MarshalBinary(sendTxBefore) encodedSendTx, err := cdc.MarshalBinaryLengthPrefixed(sendTxBefore)
require.Nil(t, err, "Error encoding sendTx") require.Nil(t, err, "Error encoding sendTx")
@ -69,7 +69,7 @@ func TestEncoding(t *testing.T) {
Signature: sig, Signature: sig,
} }
encodedIssueTx, err2 := cdc.MarshalBinary(issueTxBefore) encodedIssueTx, err2 := cdc.MarshalBinaryLengthPrefixed(issueTxBefore)
require.Nil(t, err2, "Error encoding issueTx") require.Nil(t, err2, "Error encoding issueTx")

View File

@ -41,7 +41,6 @@ func main() {
appInit := server.DefaultAppInit appInit := server.DefaultAppInit
rootCmd.AddCommand(InitCmd(ctx, cdc, appInit)) rootCmd.AddCommand(InitCmd(ctx, cdc, appInit))
rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, appInit))
server.AddCommands(ctx, cdc, rootCmd, appInit, server.AddCommands(ctx, cdc, rootCmd, appInit,
newApp, exportAppStateAndTMValidators) newApp, exportAppStateAndTMValidators)
@ -85,7 +84,8 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob
return err return err
} }
appState, err := appInit.AppGenState(cdc, []json.RawMessage{genTx}) appState, err := appInit.AppGenState(
cdc, tmtypes.GenesisDoc{}, []json.RawMessage{genTx})
if err != nil { if err != nil {
return err return err
} }
@ -108,13 +108,15 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob
return err return err
} }
fmt.Fprintf(os.Stderr, "%s\n", string(out)) fmt.Fprintf(os.Stderr, "%s\n", string(out))
return gaiaInit.WriteGenesisFile(config.GenesisFile(), chainID, []tmtypes.GenesisValidator{validator}, appStateJSON) return gaiaInit.WriteGenesisFile(config.GenesisFile(), chainID,
[]tmtypes.GenesisValidator{validator}, appStateJSON)
}, },
} }
cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory") cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory")
cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory") cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory")
cmd.Flags().String(client.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") cmd.Flags().String(client.FlagChainID, "",
"genesis file chain-id, if left blank will be randomly created")
cmd.Flags().String(client.FlagName, "", "validator's moniker") cmd.Flags().String(client.FlagName, "", "validator's moniker")
cmd.MarkFlagRequired(client.FlagName) cmd.MarkFlagRequired(client.FlagName)
return cmd return cmd
@ -124,7 +126,8 @@ func newApp(logger log.Logger, db dbm.DB, storeTracer io.Writer) abci.Applicatio
return app.NewBasecoinApp(logger, db, baseapp.SetPruning(viper.GetString("pruning"))) return app.NewBasecoinApp(logger, db, baseapp.SetPruning(viper.GetString("pruning")))
} }
func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB, storeTracer io.Writer) (json.RawMessage, []tmtypes.GenesisValidator, error) { func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB, storeTracer io.Writer) (
json.RawMessage, []tmtypes.GenesisValidator, error) {
bapp := app.NewBasecoinApp(logger, db) bapp := app.NewBasecoinApp(logger, db)
return bapp.ExportAppStateAndValidators() return bapp.ExportAppStateAndValidators()
} }

View File

@ -36,8 +36,9 @@ var CoolAppInit = server.AppInit{
} }
// coolGenAppParams sets up the app_state and appends the cool app state // coolGenAppParams sets up the app_state and appends the cool app state
func CoolAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (appState json.RawMessage, err error) { func CoolAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) (
appState, err = server.SimpleAppGenState(cdc, appGenTxs) appState json.RawMessage, err error) {
appState, err = server.SimpleAppGenState(cdc, tmtypes.GenesisDoc{}, appGenTxs)
if err != nil { if err != nil {
return return
} }
@ -90,7 +91,8 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob
return err return err
} }
appState, err := appInit.AppGenState(cdc, []json.RawMessage{genTx}) appState, err := appInit.AppGenState(cdc, tmtypes.GenesisDoc{},
[]json.RawMessage{genTx})
if err != nil { if err != nil {
return err return err
} }
@ -113,13 +115,15 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob
return err return err
} }
fmt.Fprintf(os.Stderr, "%s\n", string(out)) fmt.Fprintf(os.Stderr, "%s\n", string(out))
return gaiaInit.WriteGenesisFile(config.GenesisFile(), chainID, []tmtypes.GenesisValidator{validator}, appStateJSON) return gaiaInit.WriteGenesisFile(config.GenesisFile(), chainID,
[]tmtypes.GenesisValidator{validator}, appStateJSON)
}, },
} }
cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory") cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory")
cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory") cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory")
cmd.Flags().String(client.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") cmd.Flags().String(client.FlagChainID, "",
"genesis file chain-id, if left blank will be randomly created")
cmd.Flags().String(client.FlagName, "", "validator's moniker") cmd.Flags().String(client.FlagName, "", "validator's moniker")
cmd.MarkFlagRequired(client.FlagName) cmd.MarkFlagRequired(client.FlagName)
return cmd return cmd
@ -129,7 +133,8 @@ func newApp(logger log.Logger, db dbm.DB, _ io.Writer) abci.Application {
return app.NewDemocoinApp(logger, db) return app.NewDemocoinApp(logger, db)
} }
func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB, _ io.Writer) (json.RawMessage, []tmtypes.GenesisValidator, error) { func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB, _ io.Writer) (
json.RawMessage, []tmtypes.GenesisValidator, error) {
dapp := app.NewDemocoinApp(logger, db) dapp := app.NewDemocoinApp(logger, db)
return dapp.ExportAppStateAndValidators() return dapp.ExportAppStateAndValidators()
} }

View File

@ -82,8 +82,13 @@ func (vs *ValidatorSet) IterateValidators(ctx sdk.Context, fn func(index int64,
} }
} }
// IterateValidatorsBonded implements sdk.ValidatorSet // IterateBondedValidatorsByPower implements sdk.ValidatorSet
func (vs *ValidatorSet) IterateValidatorsBonded(ctx sdk.Context, fn func(index int64, Validator sdk.Validator) bool) { func (vs *ValidatorSet) IterateBondedValidatorsByPower(ctx sdk.Context, fn func(index int64, Validator sdk.Validator) bool) {
vs.IterateValidators(ctx, fn)
}
// IterateLastValidators implements sdk.ValidatorSet
func (vs *ValidatorSet) IterateLastValidators(ctx sdk.Context, fn func(index int64, Validator sdk.Validator) bool) {
vs.IterateValidators(ctx, fn) vs.IterateValidators(ctx, fn)
} }

View File

@ -71,7 +71,7 @@ func (keeper Keeper) Info(ctx sdk.Context, p Payload) (res Info) {
if bz == nil { if bz == nil {
return EmptyInfo(ctx) return EmptyInfo(ctx)
} }
keeper.cdc.MustUnmarshalBinary(bz, &res) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &res)
return return
} }
@ -80,7 +80,7 @@ func (keeper Keeper) setInfo(ctx sdk.Context, p Payload, info Info) {
store := ctx.KVStore(keeper.key) store := ctx.KVStore(keeper.key)
key := GetInfoKey(p, keeper.cdc) key := GetInfoKey(p, keeper.cdc)
bz := keeper.cdc.MustMarshalBinary(info) bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(info)
store.Set(key, bz) store.Set(key, bz)
} }

View File

@ -7,13 +7,13 @@ import (
// GetInfoKey returns the key for OracleInfo // GetInfoKey returns the key for OracleInfo
func GetInfoKey(p Payload, cdc *codec.Codec) []byte { func GetInfoKey(p Payload, cdc *codec.Codec) []byte {
bz := cdc.MustMarshalBinary(p) bz := cdc.MustMarshalBinaryLengthPrefixed(p)
return append([]byte{0x00}, bz...) return append([]byte{0x00}, bz...)
} }
// GetSignPrefix returns the prefix for signs // GetSignPrefix returns the prefix for signs
func GetSignPrefix(p Payload, cdc *codec.Codec) []byte { func GetSignPrefix(p Payload, cdc *codec.Codec) []byte {
bz := cdc.MustMarshalBinary(p) bz := cdc.MustMarshalBinaryLengthPrefixed(p)
return append([]byte{0x01}, bz...) return append([]byte{0x01}, bz...)
} }

View File

@ -82,7 +82,7 @@ func getSequence(ctx sdk.Context, key sdk.StoreKey) int {
if seqbz == nil { if seqbz == nil {
seq = 0 seq = 0
} else { } else {
codec.New().MustUnmarshalBinary(seqbz, &seq) codec.New().MustUnmarshalBinaryLengthPrefixed(seqbz, &seq)
} }
return seq return seq
@ -96,7 +96,7 @@ func handleSeqOracle(ctx sdk.Context, key sdk.StoreKey, o seqOracle) sdk.Error {
return sdk.NewError(sdk.CodespaceRoot, 1, "") return sdk.NewError(sdk.CodespaceRoot, 1, "")
} }
bz := codec.New().MustMarshalBinary(seq + 1) bz := codec.New().MustMarshalBinaryLengthPrefixed(seq + 1)
store.Set([]byte("seq"), bz) store.Set([]byte("seq"), bz)
return nil return nil

View File

@ -39,7 +39,7 @@ func (k Keeper) getBondInfo(ctx sdk.Context, addr sdk.AccAddress) bondInfo {
return bondInfo{} return bondInfo{}
} }
var bi bondInfo var bi bondInfo
err := k.cdc.UnmarshalBinary(bz, &bi) err := k.cdc.UnmarshalBinaryLengthPrefixed(bz, &bi)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -48,7 +48,7 @@ func (k Keeper) getBondInfo(ctx sdk.Context, addr sdk.AccAddress) bondInfo {
func (k Keeper) setBondInfo(ctx sdk.Context, addr sdk.AccAddress, bi bondInfo) { func (k Keeper) setBondInfo(ctx sdk.Context, addr sdk.AccAddress, bi bondInfo) {
store := ctx.KVStore(k.key) store := ctx.KVStore(k.key)
bz, err := k.cdc.MarshalBinary(bi) bz, err := k.cdc.MarshalBinaryLengthPrefixed(bi)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -1,6 +1,7 @@
#!/bin/bash #!/bin/bash
seeds=(1 2 4 7 9 20 32 123 124 582 1893 2989 3012 4728 37827 981928 87821 891823782 989182 89182391) seeds=(1 2 4 7 9 20 32 123 124 582 1893 2989 3012 4728 37827 981928 87821 891823782 989182 89182391 \
11 22 44 77 99 2020 3232 123123 124124 582582 18931893 29892989 30123012 47284728 37827)
blocks=$1 blocks=$1
echo "Running multi-seed simulation with seeds ${seeds[@]}" echo "Running multi-seed simulation with seeds ${seeds[@]}"

View File

@ -19,7 +19,8 @@ import (
type AppInit struct { type AppInit struct {
// AppGenState creates the core parameters initialization. It takes in a // AppGenState creates the core parameters initialization. It takes in a
// pubkey meant to represent the pubkey of the validator of this machine. // pubkey meant to represent the pubkey of the validator of this machine.
AppGenState func(cdc *codec.Codec, appGenTx []json.RawMessage) (appState json.RawMessage, err error) AppGenState func(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) (
appState json.RawMessage, err error)
} }
// SimpleGenTx is a simple genesis tx // SimpleGenTx is a simple genesis tx
@ -35,7 +36,8 @@ var DefaultAppInit = AppInit{
} }
// Generate a genesis transaction // Generate a genesis transaction
func SimpleAppGenTx(cdc *codec.Codec, pk crypto.PubKey) (appGenTx, cliPrint json.RawMessage, validator types.GenesisValidator, err error) { func SimpleAppGenTx(cdc *codec.Codec, pk crypto.PubKey) (
appGenTx, cliPrint json.RawMessage, validator types.GenesisValidator, err error) {
var addr sdk.AccAddress var addr sdk.AccAddress
var secret string var secret string
addr, secret, err = GenerateCoinKey() addr, secret, err = GenerateCoinKey()
@ -63,7 +65,8 @@ func SimpleAppGenTx(cdc *codec.Codec, pk crypto.PubKey) (appGenTx, cliPrint json
} }
// create the genesis app state // create the genesis app state
func SimpleAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (appState json.RawMessage, err error) { func SimpleAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) (
appState json.RawMessage, err error) {
if len(appGenTxs) != 1 { if len(appGenTxs) != 1 {
err = errors.New("must provide a single genesis transaction") err = errors.New("must provide a single genesis transaction")

View File

@ -3,6 +3,7 @@ package mock
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/tendermint/tendermint/types"
"path/filepath" "path/filepath"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
@ -102,7 +103,8 @@ func InitChainer(key sdk.StoreKey) func(sdk.Context, abci.RequestInitChain) abci
// AppGenState can be passed into InitCmd, returns a static string of a few // AppGenState can be passed into InitCmd, returns a static string of a few
// key-values that can be parsed by InitChainer // key-values that can be parsed by InitChainer
func AppGenState(_ *codec.Codec, _ []json.RawMessage) (appState json.RawMessage, err error) { func AppGenState(_ *codec.Codec, _ types.GenesisDoc, _ []json.RawMessage) (appState json.
RawMessage, err error) {
appState = json.RawMessage(`{ appState = json.RawMessage(`{
"values": [ "values": [
{ {
@ -119,7 +121,8 @@ func AppGenState(_ *codec.Codec, _ []json.RawMessage) (appState json.RawMessage,
} }
// AppGenStateEmpty returns an empty transaction state for mocking. // AppGenStateEmpty returns an empty transaction state for mocking.
func AppGenStateEmpty(_ *codec.Codec, _ []json.RawMessage) (appState json.RawMessage, err error) { func AppGenStateEmpty(_ *codec.Codec, _ types.GenesisDoc, _ []json.RawMessage) (
appState json.RawMessage, err error) {
appState = json.RawMessage(``) appState = json.RawMessage(``)
return return
} }

View File

@ -1,6 +1,7 @@
package mock package mock
import ( import (
"github.com/tendermint/tendermint/types"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -20,7 +21,7 @@ func TestInitApp(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// initialize it future-way // initialize it future-way
appState, err := AppGenState(nil, nil) appState, err := AppGenState(nil, types.GenesisDoc{}, nil)
require.NoError(t, err) require.NoError(t, err)
//TODO test validators in the init chain? //TODO test validators in the init chain?

View File

@ -93,7 +93,6 @@ func startStandAlone(ctx *Context, appCreator AppCreator) error {
return nil return nil
} }
// nolint: unparam
func startInProcess(ctx *Context, appCreator AppCreator) (*node.Node, error) { func startInProcess(ctx *Context, appCreator AppCreator) (*node.Node, error) {
cfg := ctx.Config cfg := ctx.Config
home := cfg.RootDir home := cfg.RootDir
@ -135,7 +134,12 @@ func startInProcess(ctx *Context, appCreator AppCreator) (*node.Node, error) {
return nil, err return nil, err
} }
// trap signal (run forever) TrapSignal(func() {
tmNode.RunForever() if tmNode.IsRunning() {
return tmNode, nil _ = tmNode.Stop()
}
})
// run forever (the node will not be returned)
select {}
} }

View File

@ -5,9 +5,9 @@ import (
"io" "io"
"sync" "sync"
"github.com/tendermint/go-amino"
"github.com/tendermint/iavl" "github.com/tendermint/iavl"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/merkle"
cmn "github.com/tendermint/tendermint/libs/common" cmn "github.com/tendermint/tendermint/libs/common"
dbm "github.com/tendermint/tendermint/libs/db" dbm "github.com/tendermint/tendermint/libs/db"
@ -210,13 +210,15 @@ func (st *iavlStore) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
res.Height = getHeight(tree, req) res.Height = getHeight(tree, req)
switch req.Path { switch req.Path {
case "/store", "/key": // Get by key case "/key": // get by key
key := req.Data // Data holds the key bytes key := req.Data // data holds the key bytes
res.Key = key res.Key = key
if !st.VersionExists(res.Height) { if !st.VersionExists(res.Height) {
res.Log = cmn.ErrorWrap(iavl.ErrVersionDoesNotExist, "").Error() res.Log = cmn.ErrorWrap(iavl.ErrVersionDoesNotExist, "").Error()
break break
} }
if req.Prove { if req.Prove {
value, proof, err := tree.GetVersionedWithProof(key, res.Height) value, proof, err := tree.GetVersionedWithProof(key, res.Height)
if err != nil { if err != nil {
@ -224,30 +226,30 @@ func (st *iavlStore) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
break break
} }
res.Value = value res.Value = value
cdc := amino.NewCodec() res.Proof = &merkle.Proof{Ops: []merkle.ProofOp{iavl.NewIAVLValueOp(key, proof).ProofOp()}}
p, err := cdc.MarshalBinary(proof)
if err != nil {
res.Log = err.Error()
break
}
res.Proof = p
} else { } else {
_, res.Value = tree.GetVersioned(key, res.Height) _, res.Value = tree.GetVersioned(key, res.Height)
} }
case "/subspace": case "/subspace":
var KVs []KVPair
subspace := req.Data subspace := req.Data
res.Key = subspace res.Key = subspace
var KVs []KVPair
iterator := sdk.KVStorePrefixIterator(st, subspace) iterator := sdk.KVStorePrefixIterator(st, subspace)
for ; iterator.Valid(); iterator.Next() { for ; iterator.Valid(); iterator.Next() {
KVs = append(KVs, KVPair{Key: iterator.Key(), Value: iterator.Value()}) KVs = append(KVs, KVPair{Key: iterator.Key(), Value: iterator.Value()})
} }
iterator.Close() iterator.Close()
res.Value = cdc.MustMarshalBinary(KVs) res.Value = cdc.MustMarshalBinaryLengthPrefixed(KVs)
default: default:
msg := fmt.Sprintf("Unexpected Query path: %v", req.Path) msg := fmt.Sprintf("Unexpected Query path: %v", req.Path)
return sdk.ErrUnknownRequest(msg).QueryResult() return sdk.ErrUnknownRequest(msg).QueryResult()
} }
return return
} }

View File

@ -394,9 +394,9 @@ func TestIAVLStoreQuery(t *testing.T) {
{Key: k1, Value: v3}, {Key: k1, Value: v3},
{Key: k2, Value: v2}, {Key: k2, Value: v2},
} }
valExpSubEmpty := cdc.MustMarshalBinary(KVs0) valExpSubEmpty := cdc.MustMarshalBinaryLengthPrefixed(KVs0)
valExpSub1 := cdc.MustMarshalBinary(KVs1) valExpSub1 := cdc.MustMarshalBinaryLengthPrefixed(KVs1)
valExpSub2 := cdc.MustMarshalBinary(KVs2) valExpSub2 := cdc.MustMarshalBinaryLengthPrefixed(KVs2)
cid := iavlStore.Commit() cid := iavlStore.Commit()
ver := cid.Version ver := cid.Version
@ -459,7 +459,7 @@ func TestIAVLStoreQuery(t *testing.T) {
require.Equal(t, valExpSub2, qres.Value) require.Equal(t, valExpSub2, qres.Value)
// default (height 0) will show latest -1 // default (height 0) will show latest -1
query0 := abci.RequestQuery{Path: "/store", Data: k1} query0 := abci.RequestQuery{Path: "/key", Data: k1}
qres = iavlStore.Query(query0) qres = iavlStore.Query(query0)
require.Equal(t, uint32(sdk.CodeOK), qres.Code) require.Equal(t, uint32(sdk.CodeOK), qres.Code)
require.Equal(t, v1, qres.Value) require.Equal(t, v1, qres.Value)

View File

@ -42,21 +42,22 @@ func (m List) Len() (res uint64) {
if bz == nil { if bz == nil {
return 0 return 0
} }
m.cdc.MustUnmarshalBinary(bz, &res)
m.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &res)
return return
} }
// Get() returns the element by its index // Get() returns the element by its index
func (m List) Get(index uint64, ptr interface{}) error { func (m List) Get(index uint64, ptr interface{}) error {
bz := m.store.Get(ElemKey(index)) bz := m.store.Get(ElemKey(index))
return m.cdc.UnmarshalBinary(bz, ptr) return m.cdc.UnmarshalBinaryLengthPrefixed(bz, ptr)
} }
// Set() stores the element to the given position // Set() stores the element to the given position
// Setting element out of range will break length counting // Setting element out of range will break length counting
// Use Push() instead of Set() to append a new element // Use Push() instead of Set() to append a new element
func (m List) Set(index uint64, value interface{}) { func (m List) Set(index uint64, value interface{}) {
bz := m.cdc.MustMarshalBinary(value) bz := m.cdc.MustMarshalBinaryLengthPrefixed(value)
m.store.Set(ElemKey(index), bz) m.store.Set(ElemKey(index), bz)
} }
@ -72,7 +73,7 @@ func (m List) Delete(index uint64) {
func (m List) Push(value interface{}) { func (m List) Push(value interface{}) {
length := m.Len() length := m.Len()
m.Set(length, value) m.Set(length, value)
m.store.Set(LengthKey(), m.cdc.MustMarshalBinary(length+1)) m.store.Set(LengthKey(), m.cdc.MustMarshalBinaryLengthPrefixed(length+1))
} }
// Iterate() is used to iterate over all existing elements in the list // Iterate() is used to iterate over all existing elements in the list
@ -85,13 +86,16 @@ func (m List) Iterate(ptr interface{}, fn func(uint64) bool) {
iter := sdk.KVStorePrefixIterator(m.store, []byte{0x01}) iter := sdk.KVStorePrefixIterator(m.store, []byte{0x01})
for ; iter.Valid(); iter.Next() { for ; iter.Valid(); iter.Next() {
v := iter.Value() v := iter.Value()
m.cdc.MustUnmarshalBinary(v, ptr) m.cdc.MustUnmarshalBinaryLengthPrefixed(v, ptr)
k := iter.Key() k := iter.Key()
s := string(k[len(k)-20:]) s := string(k[len(k)-20:])
index, err := strconv.ParseUint(s, 10, 64) index, err := strconv.ParseUint(s, 10, 64)
if err != nil { if err != nil {
panic(err) panic(err)
} }
if fn(index) { if fn(index) {
break break
} }

View File

@ -2,90 +2,139 @@ package store
import ( import (
"bytes" "bytes"
"fmt"
"github.com/pkg/errors"
"github.com/tendermint/iavl" "github.com/tendermint/iavl"
"github.com/tendermint/tendermint/crypto/merkle"
cmn "github.com/tendermint/tendermint/libs/common" cmn "github.com/tendermint/tendermint/libs/common"
) )
// MultiStoreProof defines a collection of store proofs in a multi-store // MultiStoreProof defines a collection of store proofs in a multi-store
type MultiStoreProof struct { type MultiStoreProof struct {
StoreInfos []storeInfo StoreInfos []storeInfo
StoreName string
RangeProof iavl.RangeProof
} }
// buildMultiStoreProof build MultiStoreProof based on iavl proof and storeInfos func NewMultiStoreProof(storeInfos []storeInfo) *MultiStoreProof {
func buildMultiStoreProof(iavlProof []byte, storeName string, storeInfos []storeInfo) []byte { return &MultiStoreProof{StoreInfos: storeInfos}
var rangeProof iavl.RangeProof
cdc.MustUnmarshalBinary(iavlProof, &rangeProof)
msp := MultiStoreProof{
StoreInfos: storeInfos,
StoreName: storeName,
RangeProof: rangeProof,
}
proof := cdc.MustMarshalBinary(msp)
return proof
} }
// VerifyMultiStoreCommitInfo verify multiStoreCommitInfo against appHash // ComputeRootHash returns the root hash for a given multi-store proof.
func VerifyMultiStoreCommitInfo(storeName string, storeInfos []storeInfo, appHash []byte) ([]byte, error) { func (proof *MultiStoreProof) ComputeRootHash() []byte {
var substoreCommitHash []byte
var height int64
for _, storeInfo := range storeInfos {
if storeInfo.Name == storeName {
substoreCommitHash = storeInfo.Core.CommitID.Hash
height = storeInfo.Core.CommitID.Version
}
}
if len(substoreCommitHash) == 0 {
return nil, cmn.NewError("failed to get substore root commit hash by store name")
}
ci := commitInfo{ ci := commitInfo{
Version: height, Version: -1, // TODO: Not needed; improve code.
StoreInfos: storeInfos, StoreInfos: proof.StoreInfos,
} }
if !bytes.Equal(appHash, ci.Hash()) { return ci.Hash()
return nil, cmn.NewError("the merkle root of multiStoreCommitInfo doesn't equal to appHash")
}
return substoreCommitHash, nil
} }
// VerifyRangeProof verify iavl RangeProof // RequireProof returns whether proof is required for the subpath.
func VerifyRangeProof(key, value []byte, substoreCommitHash []byte, rangeProof *iavl.RangeProof) error {
// verify the proof to ensure data integrity.
err := rangeProof.Verify(substoreCommitHash)
if err != nil {
return errors.Wrap(err, "proof root hash doesn't equal to substore commit root hash")
}
if len(value) != 0 {
// verify existence proof
err = rangeProof.VerifyItem(key, value)
if err != nil {
return errors.Wrap(err, "failed in existence verification")
}
} else {
// verify absence proof
err = rangeProof.VerifyAbsence(key)
if err != nil {
return errors.Wrap(err, "failed in absence verification")
}
}
return nil
}
// RequireProof return whether proof is require for the subpath
func RequireProof(subpath string) bool { func RequireProof(subpath string) bool {
// Currently, only when query subpath is "/store" or "/key", will proof be included in response. // XXX: create a better convention.
// If there are some changes about proof building in iavlstore.go, we must change code here to keep consistency with iavlstore.go:212 // Currently, only when query subpath is "/key", will proof be included in
if subpath == "/store" || subpath == "/key" { // response. If there are some changes about proof building in iavlstore.go,
// we must change code here to keep consistency with iavlStore#Query.
if subpath == "/key" {
return true return true
} }
return false return false
} }
//-----------------------------------------------------------------------------
var _ merkle.ProofOperator = MultiStoreProofOp{}
// the multi-store proof operation constant value
const ProofOpMultiStore = "multistore"
// TODO: document
type MultiStoreProofOp struct {
// Encoded in ProofOp.Key
key []byte
// To encode in ProofOp.Data.
Proof *MultiStoreProof `json:"proof"`
}
func NewMultiStoreProofOp(key []byte, proof *MultiStoreProof) MultiStoreProofOp {
return MultiStoreProofOp{
key: key,
Proof: proof,
}
}
// MultiStoreProofOpDecoder returns a multi-store merkle proof operator from a
// given proof operation.
func MultiStoreProofOpDecoder(pop merkle.ProofOp) (merkle.ProofOperator, error) {
if pop.Type != ProofOpMultiStore {
return nil, cmn.NewError("unexpected ProofOp.Type; got %v, want %v", pop.Type, ProofOpMultiStore)
}
// XXX: a bit strange as we'll discard this, but it works
var op MultiStoreProofOp
err := cdc.UnmarshalBinaryLengthPrefixed(pop.Data, &op)
if err != nil {
return nil, cmn.ErrorWrap(err, "decoding ProofOp.Data into MultiStoreProofOp")
}
return NewMultiStoreProofOp(pop.Key, op.Proof), nil
}
// ProofOp return a merkle proof operation from a given multi-store proof
// operation.
func (op MultiStoreProofOp) ProofOp() merkle.ProofOp {
bz := cdc.MustMarshalBinaryLengthPrefixed(op)
return merkle.ProofOp{
Type: ProofOpMultiStore,
Key: op.key,
Data: bz,
}
}
// String implements the Stringer interface for a mult-store proof operation.
func (op MultiStoreProofOp) String() string {
return fmt.Sprintf("MultiStoreProofOp{%v}", op.GetKey())
}
// GetKey returns the key for a multi-store proof operation.
func (op MultiStoreProofOp) GetKey() []byte {
return op.key
}
// Run executes a multi-store proof operation for a given value. It returns
// the root hash if the value matches all the store's commitID's hash or an
// error otherwise.
func (op MultiStoreProofOp) Run(args [][]byte) ([][]byte, error) {
if len(args) != 1 {
return nil, cmn.NewError("Value size is not 1")
}
value := args[0]
root := op.Proof.ComputeRootHash()
for _, si := range op.Proof.StoreInfos {
if si.Name == string(op.key) {
if bytes.Equal(value, si.Core.CommitID.Hash) {
return [][]byte{root}, nil
}
return nil, cmn.NewError("hash mismatch for substore %v: %X vs %X", si.Name, si.Core.CommitID.Hash, value)
}
}
return nil, cmn.NewError("key %v not found in multistore proof", op.key)
}
//-----------------------------------------------------------------------------
// XXX: This should be managed by the rootMultiStore which may want to register
// more proof ops?
func DefaultProofRuntime() (prt *merkle.ProofRuntime) {
prt = merkle.NewProofRuntime()
prt.RegisterOpDecoder(merkle.ProofOpSimpleValue, merkle.SimpleValueOpDecoder)
prt.RegisterOpDecoder(iavl.ProofOpIAVLValue, iavl.IAVLValueOpDecoder)
prt.RegisterOpDecoder(iavl.ProofOpIAVLAbsence, iavl.IAVLAbsenceOpDecoder)
prt.RegisterOpDecoder(ProofOpMultiStore, MultiStoreProofOpDecoder)
return
}

View File

@ -1,123 +1,108 @@
package store package store
import ( import (
"encoding/hex"
"testing" "testing"
"github.com/stretchr/testify/assert" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/tendermint/iavl" abci "github.com/tendermint/tendermint/abci/types"
cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/db"
) )
func TestVerifyMultiStoreCommitInfo(t *testing.T) { func TestVerifyIAVLStoreQueryProof(t *testing.T) {
appHash, _ := hex.DecodeString("69959B1B4E68E0F7BD3551A50C8F849B81801AF2") // Create main tree for testing.
db := dbm.NewMemDB()
substoreRootHash, _ := hex.DecodeString("ea5d468431015c2cd6295e9a0bb1fc0e49033828") iStore, err := LoadIAVLStore(db, CommitID{}, sdk.PruneNothing)
storeName := "acc" store := iStore.(*iavlStore)
var storeInfos []storeInfo
gocRootHash, _ := hex.DecodeString("62c171bb022e47d1f745608ff749e676dbd25f78")
storeInfos = append(storeInfos, storeInfo{
Name: "gov",
Core: storeCore{
CommitID: CommitID{
Version: 689,
Hash: gocRootHash,
},
},
})
storeInfos = append(storeInfos, storeInfo{
Name: "main",
Core: storeCore{
CommitID: CommitID{
Version: 689,
Hash: nil,
},
},
})
accRootHash, _ := hex.DecodeString("ea5d468431015c2cd6295e9a0bb1fc0e49033828")
storeInfos = append(storeInfos, storeInfo{
Name: "acc",
Core: storeCore{
CommitID: CommitID{
Version: 689,
Hash: accRootHash,
},
},
})
storeInfos = append(storeInfos, storeInfo{
Name: "ibc",
Core: storeCore{
CommitID: CommitID{
Version: 689,
Hash: nil,
},
},
})
stakeRootHash, _ := hex.DecodeString("987d1d27b8771d93aa3691262f661d2c85af7ca4")
storeInfos = append(storeInfos, storeInfo{
Name: "stake",
Core: storeCore{
CommitID: CommitID{
Version: 689,
Hash: stakeRootHash,
},
},
})
slashingRootHash, _ := hex.DecodeString("388ee6e5b11f367069beb1eefd553491afe9d73e")
storeInfos = append(storeInfos, storeInfo{
Name: "slashing",
Core: storeCore{
CommitID: CommitID{
Version: 689,
Hash: slashingRootHash,
},
},
})
commitHash, err := VerifyMultiStoreCommitInfo(storeName, storeInfos, appHash)
require.Nil(t, err) require.Nil(t, err)
require.Equal(t, commitHash, substoreRootHash) store.Set([]byte("MYKEY"), []byte("MYVALUE"))
cid := store.Commit()
appHash, _ = hex.DecodeString("29de216bf5e2531c688de36caaf024cd3bb09ee3") // Get Proof
res := store.Query(abci.RequestQuery{
Path: "/key", // required path to get key/value+proof
Data: []byte("MYKEY"),
Prove: true,
})
require.NotNil(t, res.Proof)
_, err = VerifyMultiStoreCommitInfo(storeName, storeInfos, appHash) // Verify proof.
require.Error(t, err, "appHash doesn't match to the merkle root of multiStoreCommitInfo") prt := DefaultProofRuntime()
err = prt.VerifyValue(res.Proof, cid.Hash, "/MYKEY", []byte("MYVALUE"))
require.Nil(t, err)
// Verify (bad) proof.
err = prt.VerifyValue(res.Proof, cid.Hash, "/MYKEY_NOT", []byte("MYVALUE"))
require.NotNil(t, err)
// Verify (bad) proof.
err = prt.VerifyValue(res.Proof, cid.Hash, "/MYKEY/MYKEY", []byte("MYVALUE"))
require.NotNil(t, err)
// Verify (bad) proof.
err = prt.VerifyValue(res.Proof, cid.Hash, "MYKEY", []byte("MYVALUE"))
require.NotNil(t, err)
// Verify (bad) proof.
err = prt.VerifyValue(res.Proof, cid.Hash, "/MYKEY", []byte("MYVALUE_NOT"))
require.NotNil(t, err)
// Verify (bad) proof.
err = prt.VerifyValue(res.Proof, cid.Hash, "/MYKEY", []byte(nil))
require.NotNil(t, err)
} }
func TestVerifyRangeProof(t *testing.T) { func TestVerifyMultiStoreQueryProof(t *testing.T) {
tree := iavl.NewMutableTree(db.NewMemDB(), 0) // Create main tree for testing.
db := dbm.NewMemDB()
store := NewCommitMultiStore(db)
iavlStoreKey := sdk.NewKVStoreKey("iavlStoreKey")
rand := cmn.NewRand() store.MountStoreWithDB(iavlStoreKey, sdk.StoreTypeIAVL, nil)
rand.Seed(0) // for determinism store.LoadVersion(0)
for _, ikey := range []byte{0x11, 0x32, 0x50, 0x72, 0x99} {
key := []byte{ikey}
tree.Set(key, []byte(rand.Str(8)))
}
root := tree.WorkingHash() iavlStore := store.GetCommitStore(iavlStoreKey).(*iavlStore)
iavlStore.Set([]byte("MYKEY"), []byte("MYVALUE"))
cid := store.Commit()
key := []byte{0x32} // Get Proof
val, proof, err := tree.GetWithProof(key) res := store.Query(abci.RequestQuery{
assert.Nil(t, err) Path: "/iavlStoreKey/key", // required path to get key/value+proof
assert.NotEmpty(t, val) Data: []byte("MYKEY"),
assert.NotEmpty(t, proof) Prove: true,
err = VerifyRangeProof(key, val, root, proof) })
assert.Nil(t, err) require.NotNil(t, res.Proof)
key = []byte{0x40} // Verify proof.
val, proof, err = tree.GetWithProof(key) prt := DefaultProofRuntime()
assert.Nil(t, err) err := prt.VerifyValue(res.Proof, cid.Hash, "/iavlStoreKey/MYKEY", []byte("MYVALUE"))
assert.Empty(t, val) require.Nil(t, err)
assert.NotEmpty(t, proof)
err = VerifyRangeProof(key, val, root, proof) // Verify proof.
assert.Nil(t, err) err = prt.VerifyValue(res.Proof, cid.Hash, "/iavlStoreKey/MYKEY", []byte("MYVALUE"))
require.Nil(t, err)
// Verify (bad) proof.
err = prt.VerifyValue(res.Proof, cid.Hash, "/iavlStoreKey/MYKEY_NOT", []byte("MYVALUE"))
require.NotNil(t, err)
// Verify (bad) proof.
err = prt.VerifyValue(res.Proof, cid.Hash, "/iavlStoreKey/MYKEY/MYKEY", []byte("MYVALUE"))
require.NotNil(t, err)
// Verify (bad) proof.
err = prt.VerifyValue(res.Proof, cid.Hash, "iavlStoreKey/MYKEY", []byte("MYVALUE"))
require.NotNil(t, err)
// Verify (bad) proof.
err = prt.VerifyValue(res.Proof, cid.Hash, "/MYKEY", []byte("MYVALUE"))
require.NotNil(t, err)
// Verify (bad) proof.
err = prt.VerifyValue(res.Proof, cid.Hash, "/iavlStoreKey/MYKEY", []byte("MYVALUE_NOT"))
require.NotNil(t, err)
// Verify (bad) proof.
err = prt.VerifyValue(res.Proof, cid.Hash, "/iavlStoreKey/MYKEY", []byte(nil))
require.NotNil(t, err)
} }

View File

@ -27,12 +27,12 @@ func (m Queue) getTop() (res uint64) {
return 0 return 0
} }
m.List.cdc.MustUnmarshalBinary(bz, &res) m.List.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &res)
return return
} }
func (m Queue) setTop(top uint64) { func (m Queue) setTop(top uint64) {
bz := m.List.cdc.MustMarshalBinary(top) bz := m.List.cdc.MustMarshalBinaryLengthPrefixed(top)
m.List.store.Set(TopKey(), bz) m.List.store.Set(TopKey(), bz)
} }

View File

@ -81,7 +81,7 @@ func TestKeys(t *testing.T) {
var actual int var actual int
// Checking keys.LengthKey // Checking keys.LengthKey
err := cdc.UnmarshalBinary(store.Get(LengthKey()), &len) err := cdc.UnmarshalBinaryLengthPrefixed(store.Get(LengthKey()), &len)
require.Nil(t, err) require.Nil(t, err)
require.Equal(t, len, queue.List.Len()) require.Equal(t, len, queue.List.Len())
@ -89,14 +89,14 @@ func TestKeys(t *testing.T) {
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
queue.List.Get(uint64(i), &expected) queue.List.Get(uint64(i), &expected)
bz := store.Get(ElemKey(uint64(i))) bz := store.Get(ElemKey(uint64(i)))
err = cdc.UnmarshalBinary(bz, &actual) err = cdc.UnmarshalBinaryLengthPrefixed(bz, &actual)
require.Nil(t, err) require.Nil(t, err)
require.Equal(t, expected, actual) require.Equal(t, expected, actual)
} }
queue.Pop() queue.Pop()
err = cdc.UnmarshalBinary(store.Get(TopKey()), &top) err = cdc.UnmarshalBinaryLengthPrefixed(store.Get(TopKey()), &top)
require.Nil(t, err) require.Nil(t, err)
require.Equal(t, top, queue.getTop()) require.Equal(t, top, queue.getTop())
} }

View File

@ -300,8 +300,14 @@ func (rs *rootMultiStore) Query(req abci.RequestQuery) abci.ResponseQuery {
return sdk.ErrInternal(errMsg.Error()).QueryResult() return sdk.ErrInternal(errMsg.Error()).QueryResult()
} }
res.Proof = buildMultiStoreProof(res.Proof, storeName, commitInfo.StoreInfos) // Restore origin path and append proof op.
res.Proof.Ops = append(res.Proof.Ops, NewMultiStoreProofOp(
[]byte(storeName),
NewMultiStoreProof(commitInfo.StoreInfos),
).ProofOp())
// TODO: handle in another TM v0.26 update PR
// res.Proof = buildMultiStoreProof(res.Proof, storeName, commitInfo.StoreInfos)
return res return res
} }
@ -313,11 +319,14 @@ func parsePath(path string) (storeName string, subpath string, err sdk.Error) {
err = sdk.ErrUnknownRequest(fmt.Sprintf("invalid path: %s", path)) err = sdk.ErrUnknownRequest(fmt.Sprintf("invalid path: %s", path))
return return
} }
paths := strings.SplitN(path[1:], "/", 2) paths := strings.SplitN(path[1:], "/", 2)
storeName = paths[0] storeName = paths[0]
if len(paths) == 2 { if len(paths) == 2 {
subpath = "/" + paths[1] subpath = "/" + paths[1]
} }
return return
} }
@ -386,11 +395,12 @@ type commitInfo struct {
// Hash returns the simple merkle root hash of the stores sorted by name. // Hash returns the simple merkle root hash of the stores sorted by name.
func (ci commitInfo) Hash() []byte { func (ci commitInfo) Hash() []byte {
// TODO cache to ci.hash []byte // TODO: cache to ci.hash []byte
m := make(map[string]merkle.Hasher, len(ci.StoreInfos)) m := make(map[string][]byte, len(ci.StoreInfos))
for _, storeInfo := range ci.StoreInfos { for _, storeInfo := range ci.StoreInfos {
m[storeInfo.Name] = storeInfo m[storeInfo.Name] = storeInfo.Hash()
} }
return merkle.SimpleHashFromMap(m) return merkle.SimpleHashFromMap(m)
} }
@ -422,13 +432,15 @@ type storeCore struct {
func (si storeInfo) Hash() []byte { func (si storeInfo) Hash() []byte {
// Doesn't write Name, since merkle.SimpleHashFromMap() will // Doesn't write Name, since merkle.SimpleHashFromMap() will
// include them via the keys. // include them via the keys.
bz, _ := cdc.MarshalBinary(si.Core) // Does not error bz, _ := cdc.MarshalBinaryLengthPrefixed(si.Core)
hasher := tmhash.New() hasher := tmhash.New()
_, err := hasher.Write(bz) _, err := hasher.Write(bz)
if err != nil { if err != nil {
// TODO: Handle with #870 // TODO: Handle with #870
panic(err) panic(err)
} }
return hasher.Sum(nil) return hasher.Sum(nil)
} }
@ -441,16 +453,18 @@ func getLatestVersion(db dbm.DB) int64 {
if latestBytes == nil { if latestBytes == nil {
return 0 return 0
} }
err := cdc.UnmarshalBinary(latestBytes, &latest)
err := cdc.UnmarshalBinaryLengthPrefixed(latestBytes, &latest)
if err != nil { if err != nil {
panic(err) panic(err)
} }
return latest return latest
} }
// Set the latest version. // Set the latest version.
func setLatestVersion(batch dbm.Batch, version int64) { func setLatestVersion(batch dbm.Batch, version int64) {
latestBytes, _ := cdc.MarshalBinary(version) // Does not error latestBytes, _ := cdc.MarshalBinaryLengthPrefixed(version)
batch.Set([]byte(latestVersionKey), latestBytes) batch.Set([]byte(latestVersionKey), latestBytes)
} }
@ -491,21 +505,19 @@ func getCommitInfo(db dbm.DB, ver int64) (commitInfo, error) {
return commitInfo{}, fmt.Errorf("failed to get rootMultiStore: no data") return commitInfo{}, fmt.Errorf("failed to get rootMultiStore: no data")
} }
// Parse bytes.
var cInfo commitInfo var cInfo commitInfo
err := cdc.UnmarshalBinary(cInfoBytes, &cInfo)
err := cdc.UnmarshalBinaryLengthPrefixed(cInfoBytes, &cInfo)
if err != nil { if err != nil {
return commitInfo{}, fmt.Errorf("failed to get rootMultiStore: %v", err) return commitInfo{}, fmt.Errorf("failed to get rootMultiStore: %v", err)
} }
return cInfo, nil return cInfo, nil
} }
// Set a commitInfo for given version. // Set a commitInfo for given version.
func setCommitInfo(batch dbm.Batch, version int64, cInfo commitInfo) { func setCommitInfo(batch dbm.Batch, version int64, cInfo commitInfo) {
cInfoBytes, err := cdc.MarshalBinary(cInfo) cInfoBytes := cdc.MustMarshalBinaryLengthPrefixed(cInfo)
if err != nil {
panic(err)
}
cInfoKey := fmt.Sprintf(commitInfoKeyFmt, version) cInfoKey := fmt.Sprintf(commitInfoKeyFmt, version)
batch.Set([]byte(cInfoKey), cInfoBytes) batch.Set([]byte(cInfoKey), cInfoBytes)
} }

View File

@ -215,7 +215,7 @@ func getExpectedCommitID(store *rootMultiStore, ver int64) CommitID {
} }
func hashStores(stores map[StoreKey]CommitStore) []byte { func hashStores(stores map[StoreKey]CommitStore) []byte {
m := make(map[string]merkle.Hasher, len(stores)) m := make(map[string][]byte, len(stores))
for key, store := range stores { for key, store := range stores {
name := key.Name() name := key.Name()
m[name] = storeInfo{ m[name] = storeInfo{
@ -224,7 +224,7 @@ func hashStores(stores map[StoreKey]CommitStore) []byte {
CommitID: store.LastCommitID(), CommitID: store.LastCommitID(),
// StoreType: store.GetStoreType(), // StoreType: store.GetStoreType(),
}, },
} }.Hash()
} }
return merkle.SimpleHashFromMap(m) return merkle.SimpleHashFromMap(m)
} }

View File

@ -305,11 +305,11 @@ func TestSerializationGocodecJSON(t *testing.T) {
func TestSerializationGocodecBinary(t *testing.T) { func TestSerializationGocodecBinary(t *testing.T) {
d := mustNewDecFromStr(t, "0.333") d := mustNewDecFromStr(t, "0.333")
bz, err := cdc.MarshalBinary(d) bz, err := cdc.MarshalBinaryLengthPrefixed(d)
require.NoError(t, err) require.NoError(t, err)
var d2 Dec var d2 Dec
err = cdc.UnmarshalBinary(bz, &d2) err = cdc.UnmarshalBinaryLengthPrefixed(bz, &d2)
require.NoError(t, err) require.NoError(t, err)
require.True(t, d.Equal(d2), "original: %v, unmarshalled: %v", d, d2) require.True(t, d.Equal(d2), "original: %v, unmarshalled: %v", d, d2)
} }
@ -323,11 +323,11 @@ type testDEmbedStruct struct {
// TODO make work for UnmarshalJSON // TODO make work for UnmarshalJSON
func TestEmbeddedStructSerializationGocodec(t *testing.T) { func TestEmbeddedStructSerializationGocodec(t *testing.T) {
obj := testDEmbedStruct{"foo", 10, NewDecWithPrec(1, 3)} obj := testDEmbedStruct{"foo", 10, NewDecWithPrec(1, 3)}
bz, err := cdc.MarshalBinary(obj) bz, err := cdc.MarshalBinaryLengthPrefixed(obj)
require.Nil(t, err) require.Nil(t, err)
var obj2 testDEmbedStruct var obj2 testDEmbedStruct
err = cdc.UnmarshalBinary(bz, &obj2) err = cdc.UnmarshalBinaryLengthPrefixed(bz, &obj2)
require.Nil(t, err) require.Nil(t, err)
require.Equal(t, obj.Field1, obj2.Field1) require.Equal(t, obj.Field1, obj2.Field1)

View File

@ -64,7 +64,11 @@ type ValidatorSet interface {
func(index int64, validator Validator) (stop bool)) func(index int64, validator Validator) (stop bool))
// iterate through bonded validators by operator address, execute func for each validator // iterate through bonded validators by operator address, execute func for each validator
IterateValidatorsBonded(Context, IterateBondedValidatorsByPower(Context,
func(index int64, validator Validator) (stop bool))
// iterate through the consensus validator set of the last block by operator address, execute func for each validator
IterateLastValidators(Context,
func(index int64, validator Validator) (stop bool)) func(index int64, validator Validator) (stop bool))
Validator(Context, ValAddress) Validator // get a particular validator by operator address Validator(Context, ValAddress) Validator // get a particular validator by operator address

View File

@ -93,16 +93,16 @@ func TestBaseAccountMarshal(t *testing.T) {
cdc := codec.New() cdc := codec.New()
codec.RegisterCrypto(cdc) codec.RegisterCrypto(cdc)
b, err := cdc.MarshalBinary(acc) b, err := cdc.MarshalBinaryLengthPrefixed(acc)
require.Nil(t, err) require.Nil(t, err)
acc2 := BaseAccount{} acc2 := BaseAccount{}
err = cdc.UnmarshalBinary(b, &acc2) err = cdc.UnmarshalBinaryLengthPrefixed(b, &acc2)
require.Nil(t, err) require.Nil(t, err)
require.Equal(t, acc, acc2) require.Equal(t, acc, acc2)
// error on bad bytes // error on bad bytes
acc2 = BaseAccount{} acc2 = BaseAccount{}
err = cdc.UnmarshalBinary(b[:len(b)/2], &acc2) err = cdc.UnmarshalBinaryLengthPrefixed(b[:len(b)/2], &acc2)
require.NotNil(t, err) require.NotNil(t, err)
} }

View File

@ -125,7 +125,8 @@ func (bldr TxBuilder) Sign(name, passphrase string, msg StdSignMsg) ([]byte, err
if err != nil { if err != nil {
return nil, err return nil, err
} }
return bldr.Codec.MarshalBinary(auth.NewStdTx(msg.Msgs, msg.Fee, []auth.StdSignature{sig}, msg.Memo))
return bldr.Codec.MarshalBinaryLengthPrefixed(auth.NewStdTx(msg.Msgs, msg.Fee, []auth.StdSignature{sig}, msg.Memo))
} }
// BuildAndSign builds a single message to be signed, and signs a transaction // BuildAndSign builds a single message to be signed, and signs a transaction
@ -166,7 +167,7 @@ func (bldr TxBuilder) BuildWithPubKey(name string, msgs []sdk.Msg) ([]byte, erro
PubKey: info.GetPubKey(), PubKey: info.GetPubKey(),
}} }}
return bldr.Codec.MarshalBinary(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo)) return bldr.Codec.MarshalBinaryLengthPrefixed(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo))
} }
// SignStdTx appends a signature to a StdTx and returns a copy of a it. If append // SignStdTx appends a signature to a StdTx and returns a copy of a it. If append

View File

@ -36,12 +36,12 @@ func (fck FeeCollectionKeeper) GetCollectedFees(ctx sdk.Context) sdk.Coins {
} }
feePool := &(sdk.Coins{}) feePool := &(sdk.Coins{})
fck.cdc.MustUnmarshalBinary(bz, feePool) fck.cdc.MustUnmarshalBinaryLengthPrefixed(bz, feePool)
return *feePool return *feePool
} }
func (fck FeeCollectionKeeper) setCollectedFees(ctx sdk.Context, coins sdk.Coins) { func (fck FeeCollectionKeeper) setCollectedFees(ctx sdk.Context, coins sdk.Coins) {
bz := fck.cdc.MustMarshalBinary(coins) bz := fck.cdc.MustMarshalBinaryLengthPrefixed(coins)
store := ctx.KVStore(fck.key) store := ctx.KVStore(fck.key)
store.Set(collectedFeesKey, bz) store.Set(collectedFeesKey, bz)
} }

View File

@ -148,13 +148,13 @@ func (am AccountKeeper) GetNextAccountNumber(ctx sdk.Context) int64 {
if bz == nil { if bz == nil {
accNumber = 0 accNumber = 0
} else { } else {
err := am.cdc.UnmarshalBinary(bz, &accNumber) err := am.cdc.UnmarshalBinaryLengthPrefixed(bz, &accNumber)
if err != nil { if err != nil {
panic(err) panic(err)
} }
} }
bz = am.cdc.MustMarshalBinary(accNumber + 1) bz = am.cdc.MustMarshalBinaryLengthPrefixed(accNumber + 1)
store.Set(globalAccountNumberKey, bz) store.Set(globalAccountNumberKey, bz)
return accNumber return accNumber

View File

@ -151,10 +151,11 @@ func DefaultTxDecoder(cdc *codec.Codec) sdk.TxDecoder {
// StdTx.Msg is an interface. The concrete types // StdTx.Msg is an interface. The concrete types
// are registered by MakeTxCodec // are registered by MakeTxCodec
err := cdc.UnmarshalBinary(txBytes, &tx) err := cdc.UnmarshalBinaryLengthPrefixed(txBytes, &tx)
if err != nil { if err != nil {
return nil, sdk.ErrTxDecode("").TraceSDK(err.Error()) return nil, sdk.ErrTxDecode("").TraceSDK(err.Error())
} }
return tx, nil return tx, nil
} }
} }

View File

@ -25,7 +25,8 @@ in place of an input filename, the command reads from standard input.`,
if err != nil { if err != nil {
return return
} }
txBytes, err := cliCtx.Codec.MarshalBinary(stdTx)
txBytes, err := cliCtx.Codec.MarshalBinaryLengthPrefixed(stdTx)
if err != nil { if err != nil {
return return
} }

View File

@ -22,11 +22,12 @@ func BroadcastTxRequestHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) ht
return return
} }
txBytes, err := cliCtx.Codec.MarshalBinary(m.Tx) txBytes, err := cliCtx.Codec.MarshalBinaryLengthPrefixed(m.Tx)
if err != nil { if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return return
} }
res, err := cliCtx.BroadcastTx(txBytes) res, err := cliCtx.BroadcastTx(txBytes)
if err != nil { if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())

View File

@ -23,14 +23,14 @@ func (k Keeper) GetDelegationDistInfo(ctx sdk.Context, delAddr sdk.AccAddress,
panic("Stored delegation-distribution info should not have been nil") panic("Stored delegation-distribution info should not have been nil")
} }
k.cdc.MustUnmarshalBinary(b, &ddi) k.cdc.MustUnmarshalBinaryLengthPrefixed(b, &ddi)
return return
} }
// set the delegator distribution info // set the delegator distribution info
func (k Keeper) SetDelegationDistInfo(ctx sdk.Context, ddi types.DelegationDistInfo) { func (k Keeper) SetDelegationDistInfo(ctx sdk.Context, ddi types.DelegationDistInfo) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
b := k.cdc.MustMarshalBinary(ddi) b := k.cdc.MustMarshalBinaryLengthPrefixed(ddi)
store.Set(GetDelegationDistInfoKey(ddi.DelegatorAddr, ddi.ValOperatorAddr), b) store.Set(GetDelegationDistInfoKey(ddi.DelegatorAddr, ddi.ValOperatorAddr), b)
} }

View File

@ -13,7 +13,7 @@ func (k Keeper) GetAllValidatorDistInfos(ctx sdk.Context) (vdis []types.Validato
for ; iterator.Valid(); iterator.Next() { for ; iterator.Valid(); iterator.Next() {
var vdi types.ValidatorDistInfo var vdi types.ValidatorDistInfo
k.cdc.MustUnmarshalBinary(iterator.Value(), &vdi) k.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &vdi)
vdis = append(vdis, vdi) vdis = append(vdis, vdi)
} }
return vdis return vdis
@ -27,7 +27,7 @@ func (k Keeper) GetAllDelegationDistInfos(ctx sdk.Context) (ddis []types.Delegat
for ; iterator.Valid(); iterator.Next() { for ; iterator.Valid(); iterator.Next() {
var ddi types.DelegationDistInfo var ddi types.DelegationDistInfo
k.cdc.MustUnmarshalBinary(iterator.Value(), &ddi) k.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &ddi)
ddis = append(ddis, ddi) ddis = append(ddis, ddi)
} }
return ddis return ddis

View File

@ -1,6 +1,8 @@
package keeper package keeper
import ( import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/distribution/types" "github.com/cosmos/cosmos-sdk/x/distribution/types"
) )
@ -38,11 +40,12 @@ func (k Keeper) onValidatorBonded(ctx sdk.Context, valAddr sdk.ValAddress) {
k.onValidatorModified(ctx, valAddr) k.onValidatorModified(ctx, valAddr)
} }
// XXX Consider removing this after debugging. // Sanity check, very useful!
func (k Keeper) onValidatorPowerDidChange(ctx sdk.Context, valAddr sdk.ValAddress) { func (k Keeper) onValidatorPowerDidChange(ctx sdk.Context, valAddr sdk.ValAddress) {
vi := k.GetValidatorDistInfo(ctx, valAddr) vi := k.GetValidatorDistInfo(ctx, valAddr)
if vi.FeePoolWithdrawalHeight != ctx.BlockHeight() { if vi.FeePoolWithdrawalHeight != ctx.BlockHeight() {
panic("expected validator dist info FeePoolWithdrawalHeight to be updated, but was not.") panic(fmt.Sprintf("expected validator (%v) dist info FeePoolWithdrawalHeight to be updated to %v, but was %v.",
valAddr.String(), ctx.BlockHeight(), vi.FeePoolWithdrawalHeight))
} }
} }

View File

@ -44,14 +44,14 @@ func (k Keeper) GetFeePool(ctx sdk.Context) (feePool types.FeePool) {
if b == nil { if b == nil {
panic("Stored fee pool should not have been nil") panic("Stored fee pool should not have been nil")
} }
k.cdc.MustUnmarshalBinary(b, &feePool) k.cdc.MustUnmarshalBinaryLengthPrefixed(b, &feePool)
return return
} }
// set the global fee pool distribution info // set the global fee pool distribution info
func (k Keeper) SetFeePool(ctx sdk.Context, feePool types.FeePool) { func (k Keeper) SetFeePool(ctx sdk.Context, feePool types.FeePool) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
b := k.cdc.MustMarshalBinary(feePool) b := k.cdc.MustMarshalBinaryLengthPrefixed(feePool)
store.Set(FeePoolKey, b) store.Set(FeePoolKey, b)
} }
@ -77,14 +77,14 @@ func (k Keeper) GetPreviousProposerConsAddr(ctx sdk.Context) (consAddr sdk.ConsA
panic("Previous proposer not set") panic("Previous proposer not set")
} }
k.cdc.MustUnmarshalBinary(b, &consAddr) k.cdc.MustUnmarshalBinaryLengthPrefixed(b, &consAddr)
return return
} }
// get the proposer public key for this block // get the proposer public key for this block
func (k Keeper) SetPreviousProposerConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) { func (k Keeper) SetPreviousProposerConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
b := k.cdc.MustMarshalBinary(consAddr) b := k.cdc.MustMarshalBinaryLengthPrefixed(consAddr)
store.Set(ProposerKey, b) store.Set(ProposerKey, b)
} }

View File

@ -130,7 +130,7 @@ func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initCoins int64,
keeper := NewKeeper(cdc, keyDistr, pk.Subspace(DefaultParamspace), ck, sk, fck, types.DefaultCodespace) keeper := NewKeeper(cdc, keyDistr, pk.Subspace(DefaultParamspace), ck, sk, fck, types.DefaultCodespace)
// set the distribution hooks on staking // set the distribution hooks on staking
sk = sk.WithHooks(keeper.Hooks()) sk.SetHooks(keeper.Hooks())
// set genesis items required for distribution // set genesis items required for distribution
keeper.SetFeePool(ctx, types.InitialFeePool()) keeper.SetFeePool(ctx, types.InitialFeePool())
@ -172,7 +172,7 @@ func (k Keeper) IterateValidatorDistInfos(ctx sdk.Context,
index := int64(0) index := int64(0)
for ; iter.Valid(); iter.Next() { for ; iter.Valid(); iter.Next() {
var vdi types.ValidatorDistInfo var vdi types.ValidatorDistInfo
k.cdc.MustUnmarshalBinary(iter.Value(), &vdi) k.cdc.MustUnmarshalBinaryLengthPrefixed(iter.Value(), &vdi)
if fn(index, vdi) { if fn(index, vdi) {
return return
} }

View File

@ -23,14 +23,14 @@ func (k Keeper) GetValidatorDistInfo(ctx sdk.Context,
panic("Stored validator-distribution info should not have been nil") panic("Stored validator-distribution info should not have been nil")
} }
k.cdc.MustUnmarshalBinary(b, &vdi) k.cdc.MustUnmarshalBinaryLengthPrefixed(b, &vdi)
return return
} }
// set the validator distribution info // set the validator distribution info
func (k Keeper) SetValidatorDistInfo(ctx sdk.Context, vdi types.ValidatorDistInfo) { func (k Keeper) SetValidatorDistInfo(ctx sdk.Context, vdi types.ValidatorDistInfo) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
b := k.cdc.MustMarshalBinary(vdi) b := k.cdc.MustMarshalBinaryLengthPrefixed(vdi)
store.Set(GetValidatorDistInfoKey(vdi.OperatorAddr), b) store.Set(GetValidatorDistInfoKey(vdi.OperatorAddr), b)
} }

View File

@ -292,7 +292,7 @@ func queryDepositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han
var deposit gov.Deposit var deposit gov.Deposit
cdc.UnmarshalJSON(res, &deposit) cdc.UnmarshalJSON(res, &deposit)
if deposit.Empty() { if deposit.Empty() {
res, err := cliCtx.QueryWithData("custom/gov/proposal", cdc.MustMarshalBinary(gov.QueryProposalParams{params.ProposalID})) res, err := cliCtx.QueryWithData("custom/gov/proposal", cdc.MustMarshalBinaryLengthPrefixed(gov.QueryProposalParams{params.ProposalID}))
if err != nil || len(res) == 0 { if err != nil || len(res) == 0 {
err := errors.Errorf("proposalID [%d] does not exist", proposalID) err := errors.Errorf("proposalID [%d] does not exist", proposalID)
utils.WriteErrorResponse(w, http.StatusNotFound, err.Error()) utils.WriteErrorResponse(w, http.StatusNotFound, err.Error())

View File

@ -106,7 +106,7 @@ func (keeper Keeper) GetProposal(ctx sdk.Context, proposalID int64) Proposal {
} }
var proposal Proposal var proposal Proposal
keeper.cdc.MustUnmarshalBinary(bz, &proposal) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposal)
return proposal return proposal
} }
@ -114,7 +114,7 @@ func (keeper Keeper) GetProposal(ctx sdk.Context, proposalID int64) Proposal {
// Implements sdk.AccountKeeper. // Implements sdk.AccountKeeper.
func (keeper Keeper) SetProposal(ctx sdk.Context, proposal Proposal) { func (keeper Keeper) SetProposal(ctx sdk.Context, proposal Proposal) {
store := ctx.KVStore(keeper.storeKey) store := ctx.KVStore(keeper.storeKey)
bz := keeper.cdc.MustMarshalBinary(proposal) bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposal)
store.Set(KeyProposal(proposal.GetProposalID()), bz) store.Set(KeyProposal(proposal.GetProposalID()), bz)
} }
@ -175,7 +175,7 @@ func (keeper Keeper) setInitialProposalID(ctx sdk.Context, proposalID int64) sdk
if bz != nil { if bz != nil {
return ErrInvalidGenesis(keeper.codespace, "Initial ProposalID already set") return ErrInvalidGenesis(keeper.codespace, "Initial ProposalID already set")
} }
bz = keeper.cdc.MustMarshalBinary(proposalID) bz = keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID)
store.Set(KeyNextProposalID, bz) store.Set(KeyNextProposalID, bz)
return nil return nil
} }
@ -197,8 +197,8 @@ func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID int64, err sd
if bz == nil { if bz == nil {
return -1, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set") return -1, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set")
} }
keeper.cdc.MustUnmarshalBinary(bz, &proposalID) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalID)
bz = keeper.cdc.MustMarshalBinary(proposalID + 1) bz = keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID + 1)
store.Set(KeyNextProposalID, bz) store.Set(KeyNextProposalID, bz)
return proposalID, nil return proposalID, nil
} }
@ -210,7 +210,7 @@ func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID int64, e
if bz == nil { if bz == nil {
return -1, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set") return -1, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set")
} }
keeper.cdc.MustUnmarshalBinary(bz, &proposalID) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalID)
return proposalID, nil return proposalID, nil
} }
@ -298,13 +298,13 @@ func (keeper Keeper) GetVote(ctx sdk.Context, proposalID int64, voterAddr sdk.Ac
return Vote{}, false return Vote{}, false
} }
var vote Vote var vote Vote
keeper.cdc.MustUnmarshalBinary(bz, &vote) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &vote)
return vote, true return vote, true
} }
func (keeper Keeper) setVote(ctx sdk.Context, proposalID int64, voterAddr sdk.AccAddress, vote Vote) { func (keeper Keeper) setVote(ctx sdk.Context, proposalID int64, voterAddr sdk.AccAddress, vote Vote) {
store := ctx.KVStore(keeper.storeKey) store := ctx.KVStore(keeper.storeKey)
bz := keeper.cdc.MustMarshalBinary(vote) bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(vote)
store.Set(KeyVote(proposalID, voterAddr), bz) store.Set(KeyVote(proposalID, voterAddr), bz)
} }
@ -330,13 +330,13 @@ func (keeper Keeper) GetDeposit(ctx sdk.Context, proposalID int64, depositerAddr
return Deposit{}, false return Deposit{}, false
} }
var deposit Deposit var deposit Deposit
keeper.cdc.MustUnmarshalBinary(bz, &deposit) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &deposit)
return deposit, true return deposit, true
} }
func (keeper Keeper) setDeposit(ctx sdk.Context, proposalID int64, depositerAddr sdk.AccAddress, deposit Deposit) { func (keeper Keeper) setDeposit(ctx sdk.Context, proposalID int64, depositerAddr sdk.AccAddress, deposit Deposit) {
store := ctx.KVStore(keeper.storeKey) store := ctx.KVStore(keeper.storeKey)
bz := keeper.cdc.MustMarshalBinary(deposit) bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(deposit)
store.Set(KeyDeposit(proposalID, depositerAddr), bz) store.Set(KeyDeposit(proposalID, depositerAddr), bz)
} }
@ -398,7 +398,7 @@ func (keeper Keeper) RefundDeposits(ctx sdk.Context, proposalID int64) {
for ; depositsIterator.Valid(); depositsIterator.Next() { for ; depositsIterator.Valid(); depositsIterator.Next() {
deposit := &Deposit{} deposit := &Deposit{}
keeper.cdc.MustUnmarshalBinary(depositsIterator.Value(), deposit) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(depositsIterator.Value(), deposit)
_, _, err := keeper.ck.AddCoins(ctx, deposit.Depositer, deposit.Amount) _, _, err := keeper.ck.AddCoins(ctx, deposit.Depositer, deposit.Amount)
if err != nil { if err != nil {
@ -434,14 +434,14 @@ func (keeper Keeper) getActiveProposalQueue(ctx sdk.Context) ProposalQueue {
} }
var proposalQueue ProposalQueue var proposalQueue ProposalQueue
keeper.cdc.MustUnmarshalBinary(bz, &proposalQueue) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalQueue)
return proposalQueue return proposalQueue
} }
func (keeper Keeper) setActiveProposalQueue(ctx sdk.Context, proposalQueue ProposalQueue) { func (keeper Keeper) setActiveProposalQueue(ctx sdk.Context, proposalQueue ProposalQueue) {
store := ctx.KVStore(keeper.storeKey) store := ctx.KVStore(keeper.storeKey)
bz := keeper.cdc.MustMarshalBinary(proposalQueue) bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalQueue)
store.Set(KeyActiveProposalQueue, bz) store.Set(KeyActiveProposalQueue, bz)
} }
@ -480,14 +480,14 @@ func (keeper Keeper) getInactiveProposalQueue(ctx sdk.Context) ProposalQueue {
var proposalQueue ProposalQueue var proposalQueue ProposalQueue
keeper.cdc.MustUnmarshalBinary(bz, &proposalQueue) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalQueue)
return proposalQueue return proposalQueue
} }
func (keeper Keeper) setInactiveProposalQueue(ctx sdk.Context, proposalQueue ProposalQueue) { func (keeper Keeper) setInactiveProposalQueue(ctx sdk.Context, proposalQueue ProposalQueue) {
store := ctx.KVStore(keeper.storeKey) store := ctx.KVStore(keeper.storeKey)
bz := keeper.cdc.MustMarshalBinary(proposalQueue) bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalQueue)
store.Set(KeyInactiveProposalQueue, bz) store.Set(KeyInactiveProposalQueue, bz)
} }

View File

@ -122,11 +122,11 @@ func TestDeposits(t *testing.T) {
// Test deposit iterator // Test deposit iterator
depositsIterator := keeper.GetDeposits(ctx, proposalID) depositsIterator := keeper.GetDeposits(ctx, proposalID)
require.True(t, depositsIterator.Valid()) require.True(t, depositsIterator.Valid())
keeper.cdc.MustUnmarshalBinary(depositsIterator.Value(), &deposit) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(depositsIterator.Value(), &deposit)
require.Equal(t, addrs[0], deposit.Depositer) require.Equal(t, addrs[0], deposit.Depositer)
require.Equal(t, fourSteak.Plus(fiveSteak), deposit.Amount) require.Equal(t, fourSteak.Plus(fiveSteak), deposit.Amount)
depositsIterator.Next() depositsIterator.Next()
keeper.cdc.MustUnmarshalBinary(depositsIterator.Value(), &deposit) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(depositsIterator.Value(), &deposit)
require.Equal(t, addrs[1], deposit.Depositer) require.Equal(t, addrs[1], deposit.Depositer)
require.Equal(t, fourSteak, deposit.Amount) require.Equal(t, fourSteak, deposit.Amount)
depositsIterator.Next() depositsIterator.Next()
@ -184,14 +184,14 @@ func TestVotes(t *testing.T) {
// Test vote iterator // Test vote iterator
votesIterator := keeper.GetVotes(ctx, proposalID) votesIterator := keeper.GetVotes(ctx, proposalID)
require.True(t, votesIterator.Valid()) require.True(t, votesIterator.Valid())
keeper.cdc.MustUnmarshalBinary(votesIterator.Value(), &vote) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(votesIterator.Value(), &vote)
require.True(t, votesIterator.Valid()) require.True(t, votesIterator.Valid())
require.Equal(t, addrs[0], vote.Voter) require.Equal(t, addrs[0], vote.Voter)
require.Equal(t, proposalID, vote.ProposalID) require.Equal(t, proposalID, vote.ProposalID)
require.Equal(t, OptionYes, vote.Option) require.Equal(t, OptionYes, vote.Option)
votesIterator.Next() votesIterator.Next()
require.True(t, votesIterator.Valid()) require.True(t, votesIterator.Valid())
keeper.cdc.MustUnmarshalBinary(votesIterator.Value(), &vote) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(votesIterator.Value(), &vote)
require.True(t, votesIterator.Valid()) require.True(t, votesIterator.Valid())
require.Equal(t, addrs[1], vote.Voter) require.Equal(t, addrs[1], vote.Voter)
require.Equal(t, proposalID, vote.ProposalID) require.Equal(t, proposalID, vote.ProposalID)

View File

@ -126,7 +126,7 @@ func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper
depositsIterator := keeper.GetDeposits(ctx, params.ProposalID) depositsIterator := keeper.GetDeposits(ctx, params.ProposalID)
for ; depositsIterator.Valid(); depositsIterator.Next() { for ; depositsIterator.Valid(); depositsIterator.Next() {
deposit := Deposit{} deposit := Deposit{}
keeper.cdc.MustUnmarshalBinary(depositsIterator.Value(), &deposit) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(depositsIterator.Value(), &deposit)
deposits = append(deposits, deposit) deposits = append(deposits, deposit)
} }
@ -155,7 +155,7 @@ func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke
votesIterator := keeper.GetVotes(ctx, params.ProposalID) votesIterator := keeper.GetVotes(ctx, params.ProposalID)
for ; votesIterator.Valid(); votesIterator.Next() { for ; votesIterator.Valid(); votesIterator.Next() {
vote := Vote{} vote := Vote{}
keeper.cdc.MustUnmarshalBinary(votesIterator.Value(), &vote) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(votesIterator.Value(), &vote)
votes = append(votes, vote) votes = append(votes, vote)
} }

View File

@ -23,7 +23,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall
totalVotingPower := sdk.ZeroDec() totalVotingPower := sdk.ZeroDec()
currValidators := make(map[string]validatorGovInfo) currValidators := make(map[string]validatorGovInfo)
keeper.vs.IterateValidatorsBonded(ctx, func(index int64, validator sdk.Validator) (stop bool) { keeper.vs.IterateBondedValidatorsByPower(ctx, func(index int64, validator sdk.Validator) (stop bool) {
currValidators[validator.GetOperator().String()] = validatorGovInfo{ currValidators[validator.GetOperator().String()] = validatorGovInfo{
Address: validator.GetOperator(), Address: validator.GetOperator(),
Power: validator.GetPower(), Power: validator.GetPower(),
@ -39,7 +39,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall
defer votesIterator.Close() defer votesIterator.Close()
for ; votesIterator.Valid(); votesIterator.Next() { for ; votesIterator.Valid(); votesIterator.Next() {
vote := &Vote{} vote := &Vote{}
keeper.cdc.MustUnmarshalBinary(votesIterator.Value(), vote) keeper.cdc.MustUnmarshalBinaryLengthPrefixed(votesIterator.Value(), vote)
// if validator, just record it in the map // if validator, just record it in the map
// if delegator tally voting power // if delegator tally voting power

View File

@ -117,7 +117,7 @@ OUTER:
var processed int64 var processed int64
if processedbz == nil { if processedbz == nil {
processed = 0 processed = 0
} else if err = c.cdc.UnmarshalBinary(processedbz, &processed); err != nil { } else if err = c.cdc.UnmarshalBinaryLengthPrefixed(processedbz, &processed); err != nil {
panic(err) panic(err)
} }
@ -131,7 +131,7 @@ OUTER:
var egressLength int64 var egressLength int64
if egressLengthbz == nil { if egressLengthbz == nil {
egressLength = 0 egressLength = 0
} else if err = c.cdc.UnmarshalBinary(egressLengthbz, &egressLength); err != nil { } else if err = c.cdc.UnmarshalBinaryLengthPrefixed(egressLengthbz, &egressLength); err != nil {
panic(err) panic(err)
} }
@ -192,7 +192,7 @@ func (c relayCommander) getSequence(node string) int64 {
func (c relayCommander) refine(bz []byte, sequence int64, passphrase string) []byte { func (c relayCommander) refine(bz []byte, sequence int64, passphrase string) []byte {
var packet ibc.IBCPacket var packet ibc.IBCPacket
if err := c.cdc.UnmarshalBinary(bz, &packet); err != nil { if err := c.cdc.UnmarshalBinaryLengthPrefixed(bz, &packet); err != nil {
panic(err) panic(err)
} }

View File

@ -33,13 +33,13 @@ func (ibcm Mapper) PostIBCPacket(ctx sdk.Context, packet IBCPacket) sdk.Error {
// write everything into the state // write everything into the state
store := ctx.KVStore(ibcm.key) store := ctx.KVStore(ibcm.key)
index := ibcm.getEgressLength(store, packet.DestChain) index := ibcm.getEgressLength(store, packet.DestChain)
bz, err := ibcm.cdc.MarshalBinary(packet) bz, err := ibcm.cdc.MarshalBinaryLengthPrefixed(packet)
if err != nil { if err != nil {
panic(err) panic(err)
} }
store.Set(EgressKey(packet.DestChain, index), bz) store.Set(EgressKey(packet.DestChain, index), bz)
bz, err = ibcm.cdc.MarshalBinary(index + 1) bz, err = ibcm.cdc.MarshalBinaryLengthPrefixed(index + 1)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -61,7 +61,7 @@ func (ibcm Mapper) ReceiveIBCPacket(ctx sdk.Context, packet IBCPacket) sdk.Error
// Functions for accessing the underlying KVStore. // Functions for accessing the underlying KVStore.
func marshalBinaryPanic(cdc *codec.Codec, value interface{}) []byte { func marshalBinaryPanic(cdc *codec.Codec, value interface{}) []byte {
res, err := cdc.MarshalBinary(value) res, err := cdc.MarshalBinaryLengthPrefixed(value)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -69,7 +69,7 @@ func marshalBinaryPanic(cdc *codec.Codec, value interface{}) []byte {
} }
func unmarshalBinaryPanic(cdc *codec.Codec, bz []byte, ptr interface{}) { func unmarshalBinaryPanic(cdc *codec.Codec, bz []byte, ptr interface{}) {
err := cdc.UnmarshalBinary(bz, ptr) err := cdc.UnmarshalBinaryLengthPrefixed(bz, ptr)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -59,14 +59,14 @@ func (k Keeper) GetMinter(ctx sdk.Context) (minter Minter) {
if b == nil { if b == nil {
panic("Stored fee pool should not have been nil") panic("Stored fee pool should not have been nil")
} }
k.cdc.MustUnmarshalBinary(b, &minter) k.cdc.MustUnmarshalBinaryLengthPrefixed(b, &minter)
return return
} }
// set the minter // set the minter
func (k Keeper) SetMinter(ctx sdk.Context, minter Minter) { func (k Keeper) SetMinter(ctx sdk.Context, minter Minter) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
b := k.cdc.MustMarshalBinary(minter) b := k.cdc.MustMarshalBinaryLengthPrefixed(minter)
store.Set(minterKey, b) store.Set(minterKey, b)
} }

View File

@ -1,37 +0,0 @@
package simulation
const (
// Fraction of double-signing evidence from a past height
pastEvidenceFraction float64 = 0.5
// Minimum time per block
minTimePerBlock int64 = 1000 / 2
// Maximum time per block
maxTimePerBlock int64 = 1000
// Number of keys
numKeys int = 250
// Chance that double-signing evidence is found on a given block
evidenceFraction float64 = 0.5
// TODO Remove in favor of binary search for invariant violation
onOperation bool = false
)
var (
// Currently there are 3 different liveness types, fully online, spotty connection, offline.
initialLivenessWeightings = []int{40, 5, 5}
livenessTransitionMatrix, _ = CreateTransitionMatrix([][]int{
{90, 20, 1},
{10, 50, 5},
{0, 10, 1000},
})
// 3 states: rand in range [0, 4*provided blocksize], rand in range [0, 2 * provided blocksize], 0
blockSizeTransitionMatrix, _ = CreateTransitionMatrix([][]int{
{85, 5, 0},
{15, 92, 1},
{0, 3, 99},
})
)

View File

@ -0,0 +1,66 @@
package simulation
import (
"math/rand"
)
const (
// Minimum time per block
minTimePerBlock int64 = 10000 / 2
// Maximum time per block
maxTimePerBlock int64 = 10000
// TODO Remove in favor of binary search for invariant violation
onOperation bool = false
)
var (
// Currently there are 3 different liveness types, fully online, spotty connection, offline.
defaultLivenessTransitionMatrix, _ = CreateTransitionMatrix([][]int{
{90, 20, 1},
{10, 50, 5},
{0, 10, 1000},
})
// 3 states: rand in range [0, 4*provided blocksize], rand in range [0, 2 * provided blocksize], 0
defaultBlockSizeTransitionMatrix, _ = CreateTransitionMatrix([][]int{
{85, 5, 0},
{15, 92, 1},
{0, 3, 99},
})
)
// Simulation parameters
type Params struct {
PastEvidenceFraction float64
NumKeys int
EvidenceFraction float64
InitialLivenessWeightings []int
LivenessTransitionMatrix TransitionMatrix
BlockSizeTransitionMatrix TransitionMatrix
}
// Return default simulation parameters
func DefaultParams() Params {
return Params{
PastEvidenceFraction: 0.5,
NumKeys: 250,
EvidenceFraction: 0.5,
InitialLivenessWeightings: []int{40, 5, 5},
LivenessTransitionMatrix: defaultLivenessTransitionMatrix,
BlockSizeTransitionMatrix: defaultBlockSizeTransitionMatrix,
}
}
// Return random simulation parameters
func RandomParams(r *rand.Rand) Params {
return Params{
PastEvidenceFraction: r.Float64(),
NumKeys: r.Intn(250),
EvidenceFraction: r.Float64(),
InitialLivenessWeightings: []int{r.Intn(80), r.Intn(10), r.Intn(10)},
LivenessTransitionMatrix: defaultLivenessTransitionMatrix,
BlockSizeTransitionMatrix: defaultBlockSizeTransitionMatrix,
}
}

View File

@ -14,7 +14,7 @@ import (
"time" "time"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
common "github.com/tendermint/tendermint/libs/common" cmn "github.com/tendermint/tendermint/libs/common"
tmtypes "github.com/tendermint/tendermint/types" tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/baseapp"
@ -31,13 +31,13 @@ func Simulate(t *testing.T, app *baseapp.BaseApp,
return SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize, commit) return SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize, commit)
} }
func initChain(r *rand.Rand, accounts []Account, setups []RandSetup, app *baseapp.BaseApp, func initChain(r *rand.Rand, params Params, accounts []Account, setups []RandSetup, app *baseapp.BaseApp,
appStateFn func(r *rand.Rand, accounts []Account) json.RawMessage) (validators map[string]mockValidator) { appStateFn func(r *rand.Rand, accounts []Account) json.RawMessage) (validators map[string]mockValidator) {
res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, accounts)}) res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, accounts)})
validators = make(map[string]mockValidator) validators = make(map[string]mockValidator)
for _, validator := range res.Validators { for _, validator := range res.Validators {
str := fmt.Sprintf("%v", validator.PubKey) str := fmt.Sprintf("%v", validator.PubKey)
validators[str] = mockValidator{validator, GetMemberOfInitialState(r, initialLivenessWeightings)} validators[str] = mockValidator{validator, GetMemberOfInitialState(r, params.InitialLivenessWeightings)}
} }
for i := 0; i < len(setups); i++ { for i := 0; i < len(setups); i++ {
@ -65,11 +65,13 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
testingMode, t, b := getTestingMode(tb) testingMode, t, b := getTestingMode(tb)
fmt.Printf("Starting SimulateFromSeed with randomness created with seed %d\n", int(seed)) fmt.Printf("Starting SimulateFromSeed with randomness created with seed %d\n", int(seed))
r := rand.New(rand.NewSource(seed)) r := rand.New(rand.NewSource(seed))
params := RandomParams(r) // := DefaultParams()
fmt.Printf("Randomized simulation params: %+v\n", params)
timestamp := randTimestamp(r) timestamp := randTimestamp(r)
fmt.Printf("Starting the simulation from time %v, unixtime %v\n", timestamp.UTC().Format(time.UnixDate), timestamp.Unix()) fmt.Printf("Starting the simulation from time %v, unixtime %v\n", timestamp.UTC().Format(time.UnixDate), timestamp.Unix())
timeDiff := maxTimePerBlock - minTimePerBlock timeDiff := maxTimePerBlock - minTimePerBlock
accs := RandomAccounts(r, numKeys) accs := RandomAccounts(r, params.NumKeys)
// Setup event stats // Setup event stats
events := make(map[string]uint) events := make(map[string]uint)
@ -77,7 +79,7 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
events[what]++ events[what]++
} }
validators := initChain(r, accs, setups, app, appStateFn) validators := initChain(r, params, accs, setups, app, appStateFn)
// Second variable to keep pending validator set (delayed one block since TM 0.24) // Second variable to keep pending validator set (delayed one block since TM 0.24)
// Initially this is the same as the initial validator set // Initially this is the same as the initial validator set
nextValidators := validators nextValidators := validators
@ -90,7 +92,7 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT) signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
go func() { go func() {
receivedSignal := <-c receivedSignal := <-c
fmt.Printf("Exiting early due to %s, on block %d, operation %d\n", receivedSignal, header.Height, opCount) fmt.Printf("\nExiting early due to %s, on block %d, operation %d\n", receivedSignal, header.Height, opCount)
simError = fmt.Errorf("Exited due to %s", receivedSignal) simError = fmt.Errorf("Exited due to %s", receivedSignal)
stopEarly = true stopEarly = true
}() }()
@ -98,7 +100,7 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
var pastTimes []time.Time var pastTimes []time.Time
var pastVoteInfos [][]abci.VoteInfo var pastVoteInfos [][]abci.VoteInfo
request := RandomRequestBeginBlock(r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, pastVoteInfos, event, header) request := RandomRequestBeginBlock(r, params, validators, pastTimes, pastVoteInfos, event, header)
// These are operations which have been queued by previous operations // These are operations which have been queued by previous operations
operationQueue := make(map[int][]Operation) operationQueue := make(map[int][]Operation)
timeOperationQueue := []FutureOperation{} timeOperationQueue := []FutureOperation{}
@ -108,7 +110,7 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
blockLogBuilders = make([]*strings.Builder, numBlocks) blockLogBuilders = make([]*strings.Builder, numBlocks)
} }
displayLogs := logPrinter(testingMode, blockLogBuilders) displayLogs := logPrinter(testingMode, blockLogBuilders)
blockSimulator := createBlockSimulator(testingMode, tb, t, event, invariants, ops, operationQueue, timeOperationQueue, numBlocks, blockSize, displayLogs) blockSimulator := createBlockSimulator(testingMode, tb, t, params, event, invariants, ops, operationQueue, timeOperationQueue, numBlocks, blockSize, displayLogs)
if !testingMode { if !testingMode {
b.ResetTimer() b.ResetTimer()
} else { } else {
@ -181,11 +183,11 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
} }
// Generate a random RequestBeginBlock with the current validator set for the next block // Generate a random RequestBeginBlock with the current validator set for the next block
request = RandomRequestBeginBlock(r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, pastVoteInfos, event, header) request = RandomRequestBeginBlock(r, params, validators, pastTimes, pastVoteInfos, event, header)
// Update the validator set, which will be reflected in the application on the next block // Update the validator set, which will be reflected in the application on the next block
validators = nextValidators validators = nextValidators
nextValidators = updateValidators(tb, r, validators, res.ValidatorUpdates, event) nextValidators = updateValidators(tb, r, params, validators, res.ValidatorUpdates, event)
} }
if stopEarly { if stopEarly {
DisplayEvents(events) DisplayEvents(events)
@ -203,7 +205,7 @@ type blockSimFn func(
// Returns a function to simulate blocks. Written like this to avoid constant parameters being passed everytime, to minimize // Returns a function to simulate blocks. Written like this to avoid constant parameters being passed everytime, to minimize
// memory overhead // memory overhead
func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, params Params,
event func(string), invariants []Invariant, event func(string), invariants []Invariant,
ops []WeightedOperation, operationQueue map[int][]Operation, timeOperationQueue []FutureOperation, ops []WeightedOperation, operationQueue map[int][]Operation, timeOperationQueue []FutureOperation,
totalNumBlocks int, avgBlockSize int, displayLogs func()) blockSimFn { totalNumBlocks int, avgBlockSize int, displayLogs func()) blockSimFn {
@ -231,7 +233,8 @@ func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T,
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accounts []Account, header abci.Header, logWriter func(string)) (opCount int) { accounts []Account, header abci.Header, logWriter func(string)) (opCount int) {
lastBlocksizeState, blocksize = getBlockSize(r, lastBlocksizeState, avgBlockSize) fmt.Printf("\rSimulating... block %d/%d, operation %d/%d. ", header.Height, totalNumBlocks, opCount, blocksize)
lastBlocksizeState, blocksize = getBlockSize(r, params, lastBlocksizeState, avgBlockSize)
for j := 0; j < blocksize; j++ { for j := 0; j < blocksize; j++ {
logUpdate, futureOps, err := selectOp(r)(r, app, ctx, accounts, event) logUpdate, futureOps, err := selectOp(r)(r, app, ctx, accounts, event)
logWriter(logUpdate) logWriter(logUpdate)
@ -272,11 +275,10 @@ func getTestingMode(tb testing.TB) (testingMode bool, t *testing.T, b *testing.B
// "over stuffed" blocks with average size of 2 * avgblocksize, // "over stuffed" blocks with average size of 2 * avgblocksize,
// normal sized blocks, hitting avgBlocksize on average, // normal sized blocks, hitting avgBlocksize on average,
// and empty blocks, with no txs / only txs scheduled from the past. // and empty blocks, with no txs / only txs scheduled from the past.
func getBlockSize(r *rand.Rand, lastBlockSizeState, avgBlockSize int) (state, blocksize int) { func getBlockSize(r *rand.Rand, params Params, lastBlockSizeState, avgBlockSize int) (state, blocksize int) {
// TODO: Make blockSizeTransitionMatrix non-global
// TODO: Make default blocksize transition matrix actually make the average // TODO: Make default blocksize transition matrix actually make the average
// blocksize equal to avgBlockSize. // blocksize equal to avgBlockSize.
state = blockSizeTransitionMatrix.NextState(r, lastBlockSizeState) state = params.BlockSizeTransitionMatrix.NextState(r, lastBlockSizeState)
if state == 0 { if state == 0 {
blocksize = r.Intn(avgBlockSize * 4) blocksize = r.Intn(avgBlockSize * 4)
} else if state == 1 { } else if state == 1 {
@ -363,7 +365,7 @@ func getKeys(validators map[string]mockValidator) []string {
} }
// randomProposer picks a random proposer from the current validator set // randomProposer picks a random proposer from the current validator set
func randomProposer(r *rand.Rand, validators map[string]mockValidator) common.HexBytes { func randomProposer(r *rand.Rand, validators map[string]mockValidator) cmn.HexBytes {
keys := getKeys(validators) keys := getKeys(validators)
if len(keys) == 0 { if len(keys) == 0 {
return nil return nil
@ -379,7 +381,7 @@ func randomProposer(r *rand.Rand, validators map[string]mockValidator) common.He
// RandomRequestBeginBlock generates a list of signing validators according to the provided list of validators, signing fraction, and evidence fraction // RandomRequestBeginBlock generates a list of signing validators according to the provided list of validators, signing fraction, and evidence fraction
// nolint: unparam // nolint: unparam
func RandomRequestBeginBlock(r *rand.Rand, validators map[string]mockValidator, livenessTransitions TransitionMatrix, evidenceFraction float64, func RandomRequestBeginBlock(r *rand.Rand, params Params, validators map[string]mockValidator,
pastTimes []time.Time, pastVoteInfos [][]abci.VoteInfo, event func(string), header abci.Header) abci.RequestBeginBlock { pastTimes []time.Time, pastVoteInfos [][]abci.VoteInfo, event func(string), header abci.Header) abci.RequestBeginBlock {
if len(validators) == 0 { if len(validators) == 0 {
return abci.RequestBeginBlock{Header: header} return abci.RequestBeginBlock{Header: header}
@ -388,7 +390,7 @@ func RandomRequestBeginBlock(r *rand.Rand, validators map[string]mockValidator,
i := 0 i := 0
for _, key := range getKeys(validators) { for _, key := range getKeys(validators) {
mVal := validators[key] mVal := validators[key]
mVal.livenessState = livenessTransitions.NextState(r, mVal.livenessState) mVal.livenessState = params.LivenessTransitionMatrix.NextState(r, mVal.livenessState)
signed := true signed := true
if mVal.livenessState == 1 { if mVal.livenessState == 1 {
@ -422,11 +424,11 @@ func RandomRequestBeginBlock(r *rand.Rand, validators map[string]mockValidator,
evidence := make([]abci.Evidence, 0) evidence := make([]abci.Evidence, 0)
// Anything but the first block // Anything but the first block
if len(pastTimes) > 0 { if len(pastTimes) > 0 {
for r.Float64() < evidenceFraction { for r.Float64() < params.EvidenceFraction {
height := header.Height height := header.Height
time := header.Time time := header.Time
vals := voteInfos vals := voteInfos
if r.Float64() < pastEvidenceFraction { if r.Float64() < params.PastEvidenceFraction {
height = int64(r.Intn(int(header.Height) - 1)) height = int64(r.Intn(int(header.Height) - 1))
time = pastTimes[height] time = pastTimes[height]
vals = pastVoteInfos[height] vals = pastVoteInfos[height]
@ -457,7 +459,7 @@ func RandomRequestBeginBlock(r *rand.Rand, validators map[string]mockValidator,
// updateValidators mimicks Tendermint's update logic // updateValidators mimicks Tendermint's update logic
// nolint: unparam // nolint: unparam
func updateValidators(tb testing.TB, r *rand.Rand, current map[string]mockValidator, updates []abci.ValidatorUpdate, event func(string)) map[string]mockValidator { func updateValidators(tb testing.TB, r *rand.Rand, params Params, current map[string]mockValidator, updates []abci.ValidatorUpdate, event func(string)) map[string]mockValidator {
for _, update := range updates { for _, update := range updates {
str := fmt.Sprintf("%v", update.PubKey) str := fmt.Sprintf("%v", update.PubKey)
@ -476,7 +478,7 @@ func updateValidators(tb testing.TB, r *rand.Rand, current map[string]mockValida
event("endblock/validatorupdates/updated") event("endblock/validatorupdates/updated")
} else { } else {
// Set this new validator // Set this new validator
current[str] = mockValidator{update, GetMemberOfInitialState(r, initialLivenessWeightings)} current[str] = mockValidator{update, GetMemberOfInitialState(r, params.InitialLivenessWeightings)}
event("endblock/validatorupdates/added") event("endblock/validatorupdates/added")
} }
} }

View File

@ -34,7 +34,7 @@ func GetCmdQuerySigningInfo(storeName string, cdc *codec.Codec) *cobra.Command {
} }
signingInfo := new(slashing.ValidatorSigningInfo) signingInfo := new(slashing.ValidatorSigningInfo)
cdc.MustUnmarshalBinary(res, signingInfo) cdc.MustUnmarshalBinaryLengthPrefixed(res, signingInfo)
switch viper.Get(cli.OutputFlag) { switch viper.Get(cli.OutputFlag) {

View File

@ -45,7 +45,7 @@ func signingInfoHandlerFn(cliCtx context.CLIContext, storeName string, cdc *code
var signingInfo slashing.ValidatorSigningInfo var signingInfo slashing.ValidatorSigningInfo
err = cdc.UnmarshalBinary(res, &signingInfo) err = cdc.UnmarshalBinaryLengthPrefixed(res, &signingInfo)
if err != nil { if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return return

View File

@ -49,6 +49,15 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio
panic(fmt.Sprintf("Validator consensus-address %v not found", consAddr)) panic(fmt.Sprintf("Validator consensus-address %v not found", consAddr))
} }
// Get validator.
validator := k.validatorSet.ValidatorByConsAddr(ctx, consAddr)
if validator == nil || validator.GetStatus() == sdk.Unbonded {
// Defensive.
// Simulation doesn't take unbonding periods into account, and
// Tendermint might break this assumption at some point.
return
}
// Double sign too old // Double sign too old
maxEvidenceAge := k.MaxEvidenceAge(ctx) maxEvidenceAge := k.MaxEvidenceAge(ctx)
if age > maxEvidenceAge { if age > maxEvidenceAge {
@ -80,7 +89,6 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio
k.validatorSet.Slash(ctx, consAddr, distributionHeight, power, revisedFraction) k.validatorSet.Slash(ctx, consAddr, distributionHeight, power, revisedFraction)
// Jail validator if not already jailed // Jail validator if not already jailed
validator := k.validatorSet.ValidatorByConsAddr(ctx, consAddr)
if !validator.GetJailed() { if !validator.GetJailed() {
k.validatorSet.Jail(ctx, consAddr) k.validatorSet.Jail(ctx, consAddr)
} }
@ -187,7 +195,7 @@ func (k Keeper) addPubkey(ctx sdk.Context, pubkey crypto.PubKey) {
func (k Keeper) getPubkey(ctx sdk.Context, address crypto.Address) (crypto.PubKey, error) { func (k Keeper) getPubkey(ctx sdk.Context, address crypto.Address) (crypto.PubKey, error) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
var pubkey crypto.PubKey var pubkey crypto.PubKey
err := k.cdc.UnmarshalBinary(store.Get(getAddrPubkeyRelationKey(address)), &pubkey) err := k.cdc.UnmarshalBinaryLengthPrefixed(store.Get(getAddrPubkeyRelationKey(address)), &pubkey)
if err != nil { if err != nil {
return nil, fmt.Errorf("address %v not found", address) return nil, fmt.Errorf("address %v not found", address)
} }
@ -196,7 +204,7 @@ func (k Keeper) getPubkey(ctx sdk.Context, address crypto.Address) (crypto.PubKe
func (k Keeper) setAddrPubkeyRelation(ctx sdk.Context, addr crypto.Address, pubkey crypto.PubKey) { func (k Keeper) setAddrPubkeyRelation(ctx sdk.Context, addr crypto.Address, pubkey crypto.PubKey) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshalBinary(pubkey) bz := k.cdc.MustMarshalBinaryLengthPrefixed(pubkey)
store.Set(getAddrPubkeyRelationKey(addr), bz) store.Set(getAddrPubkeyRelationKey(addr), bz)
} }

View File

@ -15,7 +15,7 @@ func (k Keeper) getValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress
found = false found = false
return return
} }
k.cdc.MustUnmarshalBinary(bz, &info) k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &info)
found = true found = true
return return
} }
@ -23,7 +23,7 @@ func (k Keeper) getValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress
// Stored by *validator* address (not operator address) // Stored by *validator* address (not operator address)
func (k Keeper) setValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress, info ValidatorSigningInfo) { func (k Keeper) setValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress, info ValidatorSigningInfo) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshalBinary(info) bz := k.cdc.MustMarshalBinaryLengthPrefixed(info)
store.Set(GetValidatorSigningInfoKey(address), bz) store.Set(GetValidatorSigningInfoKey(address), bz)
} }
@ -36,14 +36,14 @@ func (k Keeper) getValidatorMissedBlockBitArray(ctx sdk.Context, address sdk.Con
missed = false missed = false
return return
} }
k.cdc.MustUnmarshalBinary(bz, &missed) k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &missed)
return return
} }
// Stored by *validator* address (not operator address) // Stored by *validator* address (not operator address)
func (k Keeper) setValidatorMissedBlockBitArray(ctx sdk.Context, address sdk.ConsAddress, index int64, missed bool) { func (k Keeper) setValidatorMissedBlockBitArray(ctx sdk.Context, address sdk.ConsAddress, index int64, missed bool) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshalBinary(missed) bz := k.cdc.MustMarshalBinaryLengthPrefixed(missed)
store.Set(GetValidatorMissedBlockBitArrayKey(address, index), bz) store.Set(GetValidatorMissedBlockBitArrayKey(address, index), bz)
} }

View File

@ -61,14 +61,14 @@ func (k Keeper) addOrUpdateValidatorSlashingPeriod(ctx sdk.Context, slashingPeri
SlashedSoFar: slashingPeriod.SlashedSoFar, SlashedSoFar: slashingPeriod.SlashedSoFar,
} }
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshalBinary(slashingPeriodValue) bz := k.cdc.MustMarshalBinaryLengthPrefixed(slashingPeriodValue)
store.Set(GetValidatorSlashingPeriodKey(slashingPeriod.ValidatorAddr, slashingPeriod.StartHeight), bz) store.Set(GetValidatorSlashingPeriodKey(slashingPeriod.ValidatorAddr, slashingPeriod.StartHeight), bz)
} }
// Unmarshal key/value into a ValidatorSlashingPeriod // Unmarshal key/value into a ValidatorSlashingPeriod
func (k Keeper) unmarshalSlashingPeriodKeyValue(key []byte, value []byte) ValidatorSlashingPeriod { func (k Keeper) unmarshalSlashingPeriodKeyValue(key []byte, value []byte) ValidatorSlashingPeriod {
var slashingPeriodValue ValidatorSlashingPeriodValue var slashingPeriodValue ValidatorSlashingPeriodValue
k.cdc.MustUnmarshalBinary(value, &slashingPeriodValue) k.cdc.MustUnmarshalBinaryLengthPrefixed(value, &slashingPeriodValue)
address := sdk.ConsAddress(key[1 : 1+sdk.AddrLen]) address := sdk.ConsAddress(key[1 : 1+sdk.AddrLen])
startHeight := int64(binary.BigEndian.Uint64(key[1+sdk.AddrLen:1+sdk.AddrLen+8]) - uint64(stake.ValidatorUpdateDelay)) startHeight := int64(binary.BigEndian.Uint64(key[1+sdk.AddrLen:1+sdk.AddrLen+8]) - uint64(stake.ValidatorUpdateDelay))
return ValidatorSlashingPeriod{ return ValidatorSlashingPeriod{

View File

@ -87,8 +87,8 @@ func createTestInput(t *testing.T, defaults Params) (sdk.Context, bank.Keeper, s
} }
require.Nil(t, err) require.Nil(t, err)
paramstore := paramsKeeper.Subspace(DefaultParamspace) paramstore := paramsKeeper.Subspace(DefaultParamspace)
keeper := NewKeeper(cdc, keySlashing, sk, paramstore, DefaultCodespace) keeper := NewKeeper(cdc, keySlashing, &sk, paramstore, DefaultCodespace)
sk = sk.WithHooks(keeper.Hooks()) sk.SetHooks(keeper.Hooks())
require.NotPanics(t, func() { require.NotPanics(t, func() {
InitGenesis(ctx, keeper, GenesisState{defaults}, genesis) InitGenesis(ctx, keeper, GenesisState{defaults}, genesis)

View File

@ -35,11 +35,11 @@ const (
// common flagsets to add to various functions // common flagsets to add to various functions
var ( var (
fsPk = flag.NewFlagSet("", flag.ContinueOnError) FsPk = flag.NewFlagSet("", flag.ContinueOnError)
fsAmount = flag.NewFlagSet("", flag.ContinueOnError) FsAmount = flag.NewFlagSet("", flag.ContinueOnError)
fsShares = flag.NewFlagSet("", flag.ContinueOnError) fsShares = flag.NewFlagSet("", flag.ContinueOnError)
fsDescriptionCreate = flag.NewFlagSet("", flag.ContinueOnError) fsDescriptionCreate = flag.NewFlagSet("", flag.ContinueOnError)
fsCommissionCreate = flag.NewFlagSet("", flag.ContinueOnError) FsCommissionCreate = flag.NewFlagSet("", flag.ContinueOnError)
fsCommissionUpdate = flag.NewFlagSet("", flag.ContinueOnError) fsCommissionUpdate = flag.NewFlagSet("", flag.ContinueOnError)
fsDescriptionEdit = flag.NewFlagSet("", flag.ContinueOnError) fsDescriptionEdit = flag.NewFlagSet("", flag.ContinueOnError)
fsValidator = flag.NewFlagSet("", flag.ContinueOnError) fsValidator = flag.NewFlagSet("", flag.ContinueOnError)
@ -48,8 +48,8 @@ var (
) )
func init() { func init() {
fsPk.String(FlagPubKey, "", "Go-Amino encoded hex PubKey of the validator. For Ed25519 the go-amino prepend hex is 1624de6220") FsPk.String(FlagPubKey, "", "Bech32-encoded PubKey of the validator. ")
fsAmount.String(FlagAmount, "", "Amount of coins to bond") FsAmount.String(FlagAmount, "", "Amount of coins to bond")
fsShares.String(FlagSharesAmount, "", "Amount of source-shares to either unbond or redelegate as a positive integer or decimal") fsShares.String(FlagSharesAmount, "", "Amount of source-shares to either unbond or redelegate as a positive integer or decimal")
fsShares.String(FlagSharesFraction, "", "Fraction of source-shares to either unbond or redelegate as a positive integer or decimal >0 and <=1") fsShares.String(FlagSharesFraction, "", "Fraction of source-shares to either unbond or redelegate as a positive integer or decimal >0 and <=1")
fsDescriptionCreate.String(FlagMoniker, "", "validator name") fsDescriptionCreate.String(FlagMoniker, "", "validator name")
@ -57,9 +57,9 @@ func init() {
fsDescriptionCreate.String(FlagWebsite, "", "optional website") fsDescriptionCreate.String(FlagWebsite, "", "optional website")
fsDescriptionCreate.String(FlagDetails, "", "optional details") fsDescriptionCreate.String(FlagDetails, "", "optional details")
fsCommissionUpdate.String(FlagCommissionRate, "", "The new commission rate percentage") fsCommissionUpdate.String(FlagCommissionRate, "", "The new commission rate percentage")
fsCommissionCreate.String(FlagCommissionRate, "", "The initial commission rate percentage") FsCommissionCreate.String(FlagCommissionRate, "", "The initial commission rate percentage")
fsCommissionCreate.String(FlagCommissionMaxRate, "", "The maximum commission rate percentage") FsCommissionCreate.String(FlagCommissionMaxRate, "", "The maximum commission rate percentage")
fsCommissionCreate.String(FlagCommissionMaxChangeRate, "", "The maximum commission change rate percentage (per day)") FsCommissionCreate.String(FlagCommissionMaxChangeRate, "", "The maximum commission change rate percentage (per day)")
fsDescriptionEdit.String(FlagMoniker, types.DoNotModifyDesc, "validator name") fsDescriptionEdit.String(FlagMoniker, types.DoNotModifyDesc, "validator name")
fsDescriptionEdit.String(FlagIdentity, types.DoNotModifyDesc, "optional identity signature (ex. UPort or Keybase)") fsDescriptionEdit.String(FlagIdentity, types.DoNotModifyDesc, "optional identity signature (ex. UPort or Keybase)")
fsDescriptionEdit.String(FlagWebsite, types.DoNotModifyDesc, "optional website") fsDescriptionEdit.String(FlagWebsite, types.DoNotModifyDesc, "optional website")

View File

@ -103,10 +103,10 @@ func GetCmdCreateValidator(cdc *codec.Codec) *cobra.Command {
}, },
} }
cmd.Flags().AddFlagSet(fsPk) cmd.Flags().AddFlagSet(FsPk)
cmd.Flags().AddFlagSet(fsAmount) cmd.Flags().AddFlagSet(FsAmount)
cmd.Flags().AddFlagSet(fsDescriptionCreate) cmd.Flags().AddFlagSet(fsDescriptionCreate)
cmd.Flags().AddFlagSet(fsCommissionCreate) cmd.Flags().AddFlagSet(FsCommissionCreate)
cmd.Flags().AddFlagSet(fsDelegator) cmd.Flags().AddFlagSet(fsDelegator)
cmd.Flags().Bool(FlagGenesisFormat, false, "Export the transaction in gen-tx format; it implies --generate-only") cmd.Flags().Bool(FlagGenesisFormat, false, "Export the transaction in gen-tx format; it implies --generate-only")
cmd.Flags().String(FlagIP, "", fmt.Sprintf("Node's public IP. It takes effect only when used in combination with --%s", FlagGenesisFormat)) cmd.Flags().String(FlagIP, "", fmt.Sprintf("Node's public IP. It takes effect only when used in combination with --%s", FlagGenesisFormat))
@ -204,7 +204,7 @@ func GetCmdDelegate(cdc *codec.Codec) *cobra.Command {
}, },
} }
cmd.Flags().AddFlagSet(fsAmount) cmd.Flags().AddFlagSet(FsAmount)
cmd.Flags().AddFlagSet(fsValidator) cmd.Flags().AddFlagSet(fsValidator)
return cmd return cmd

View File

@ -72,7 +72,7 @@ func WriteGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
// WriteValidators returns a slice of bonded genesis validators. // WriteValidators returns a slice of bonded genesis validators.
func WriteValidators(ctx sdk.Context, keeper Keeper) (vals []tmtypes.GenesisValidator) { func WriteValidators(ctx sdk.Context, keeper Keeper) (vals []tmtypes.GenesisValidator) {
keeper.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) (stop bool) { keeper.IterateLastValidators(ctx, func(_ int64, validator sdk.Validator) (stop bool) {
vals = append(vals, tmtypes.GenesisValidator{ vals = append(vals, tmtypes.GenesisValidator{
PubKey: validator.GetConsPubKey(), PubKey: validator.GetConsPubKey(),
Power: validator.GetPower().RoundInt64(), Power: validator.GetPower().RoundInt64(),

View File

@ -31,11 +31,27 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
} }
// Called every block, update validator set // Called every block, update validator set
func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.ValidatorUpdate) { func EndBlocker(ctx sdk.Context, k keeper.Keeper) (validatorUpdates []abci.ValidatorUpdate) {
endBlockerTags := sdk.EmptyTags() endBlockerTags := sdk.EmptyTags()
// Reset the intra-transaction counter.
k.SetIntraTxCounter(ctx, 0)
// Calculate validator set changes.
//
// NOTE: ApplyAndReturnValidatorSetUpdates has to come before
// UnbondAllMatureValidatorQueue.
// This fixes a bug when the unbonding period is instant (is the case in
// some of the tests). The test expected the validator to be completely
// unbonded after the Endblocker (go from Bonded -> Unbonding during
// ApplyAndReturnValidatorSetUpdates and then Unbonding -> Unbonded during
// UnbondAllMatureValidatorQueue).
validatorUpdates = k.ApplyAndReturnValidatorSetUpdates(ctx)
// Unbond all mature validators from the unbonding queue.
k.UnbondAllMatureValidatorQueue(ctx) k.UnbondAllMatureValidatorQueue(ctx)
// Remove all mature unbonding delegations from the ubd queue.
matureUnbonds := k.DequeueAllMatureUnbondingQueue(ctx, ctx.BlockHeader().Time) matureUnbonds := k.DequeueAllMatureUnbondingQueue(ctx, ctx.BlockHeader().Time)
for _, dvPair := range matureUnbonds { for _, dvPair := range matureUnbonds {
err := k.CompleteUnbonding(ctx, dvPair.DelegatorAddr, dvPair.ValidatorAddr) err := k.CompleteUnbonding(ctx, dvPair.DelegatorAddr, dvPair.ValidatorAddr)
@ -49,6 +65,7 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Valid
)) ))
} }
// Remove all mature redelegations from the red queue.
matureRedelegations := k.DequeueAllMatureRedelegationQueue(ctx, ctx.BlockHeader().Time) matureRedelegations := k.DequeueAllMatureRedelegationQueue(ctx, ctx.BlockHeader().Time)
for _, dvvTriplet := range matureRedelegations { for _, dvvTriplet := range matureRedelegations {
err := k.CompleteRedelegation(ctx, dvvTriplet.DelegatorAddr, dvvTriplet.ValidatorSrcAddr, dvvTriplet.ValidatorDstAddr) err := k.CompleteRedelegation(ctx, dvvTriplet.DelegatorAddr, dvvTriplet.ValidatorSrcAddr, dvvTriplet.ValidatorDstAddr)
@ -62,12 +79,6 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Valid
tags.DstValidator, []byte(dvvTriplet.ValidatorDstAddr.String()), tags.DstValidator, []byte(dvvTriplet.ValidatorDstAddr.String()),
)) ))
} }
// reset the intra-transaction counter
k.SetIntraTxCounter(ctx, 0)
// calculate validator set changes
ValidatorUpdates = k.ApplyAndReturnValidatorSetUpdates(ctx)
return return
} }
@ -201,7 +212,7 @@ func handleMsgBeginUnbonding(ctx sdk.Context, msg types.MsgBeginUnbonding, k kee
return err.Result() return err.Result()
} }
finishTime := types.MsgCdc.MustMarshalBinary(ubd.MinTime) finishTime := types.MsgCdc.MustMarshalBinaryLengthPrefixed(ubd.MinTime)
tags := sdk.NewTags( tags := sdk.NewTags(
tags.Action, tags.ActionBeginUnbonding, tags.Action, tags.ActionBeginUnbonding,
@ -219,7 +230,7 @@ func handleMsgBeginRedelegate(ctx sdk.Context, msg types.MsgBeginRedelegate, k k
return err.Result() return err.Result()
} }
finishTime := types.MsgCdc.MustMarshalBinary(red.MinTime) finishTime := types.MsgCdc.MustMarshalBinaryLengthPrefixed(red.MinTime)
tags := sdk.NewTags( tags := sdk.NewTags(
tags.Action, tags.ActionBeginRedelegation, tags.Action, tags.ActionBeginRedelegation,

View File

@ -94,7 +94,7 @@ func TestValidatorByPowerIndex(t *testing.T) {
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got) require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
var finishTime time.Time var finishTime time.Time
types.MsgCdc.MustUnmarshalBinary(got.Data, &finishTime) types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
ctx = ctx.WithBlockTime(finishTime) ctx = ctx.WithBlockTime(finishTime)
EndBlocker(ctx, keeper) EndBlocker(ctx, keeper)
@ -232,7 +232,7 @@ func TestLegacyValidatorDelegations(t *testing.T) {
require.True(t, got.IsOK(), "expected begin unbonding validator msg to be ok, got %v", got) require.True(t, got.IsOK(), "expected begin unbonding validator msg to be ok, got %v", got)
var finishTime time.Time var finishTime time.Time
types.MsgCdc.MustUnmarshalBinary(got.Data, &finishTime) types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
ctx = ctx.WithBlockTime(finishTime) ctx = ctx.WithBlockTime(finishTime)
EndBlocker(ctx, keeper) EndBlocker(ctx, keeper)
@ -400,7 +400,7 @@ func TestIncrementsMsgUnbond(t *testing.T) {
got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
var finishTime time.Time var finishTime time.Time
types.MsgCdc.MustUnmarshalBinary(got.Data, &finishTime) types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
ctx = ctx.WithBlockTime(finishTime) ctx = ctx.WithBlockTime(finishTime)
EndBlocker(ctx, keeper) EndBlocker(ctx, keeper)
@ -494,11 +494,12 @@ func TestMultipleMsgCreateValidator(t *testing.T) {
got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
var finishTime time.Time var finishTime time.Time
types.MsgCdc.MustUnmarshalBinary(got.Data, &finishTime) // Jump to finishTime for unbonding period and remove from unbonding queue
types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
ctx = ctx.WithBlockTime(finishTime) ctx = ctx.WithBlockTime(finishTime)
EndBlocker(ctx, keeper) EndBlocker(ctx, keeper)
//Check that the account is unbonded // Check that the validator is deleted from state
validators := keeper.GetValidators(ctx, 100) validators := keeper.GetValidators(ctx, 100)
require.Equal(t, len(validatorAddrs)-(i+1), len(validators), require.Equal(t, len(validatorAddrs)-(i+1), len(validators),
"expected %d validators got %d", len(validatorAddrs)-(i+1), len(validators)) "expected %d validators got %d", len(validatorAddrs)-(i+1), len(validators))
@ -540,7 +541,7 @@ func TestMultipleMsgDelegate(t *testing.T) {
got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
var finishTime time.Time var finishTime time.Time
types.MsgCdc.MustUnmarshalBinary(got.Data, &finishTime) types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
ctx = ctx.WithBlockTime(finishTime) ctx = ctx.WithBlockTime(finishTime)
EndBlocker(ctx, keeper) EndBlocker(ctx, keeper)
@ -570,7 +571,7 @@ func TestJailValidator(t *testing.T) {
got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingValidator, keeper) got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingValidator, keeper)
require.True(t, got.IsOK(), "expected no error: %v", got) require.True(t, got.IsOK(), "expected no error: %v", got)
var finishTime time.Time var finishTime time.Time
types.MsgCdc.MustUnmarshalBinary(got.Data, &finishTime) types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
ctx = ctx.WithBlockTime(finishTime) ctx = ctx.WithBlockTime(finishTime)
EndBlocker(ctx, keeper) EndBlocker(ctx, keeper)
@ -586,7 +587,7 @@ func TestJailValidator(t *testing.T) {
msgBeginUnbondingDelegator := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewDec(10)) msgBeginUnbondingDelegator := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewDec(10))
got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingDelegator, keeper) got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingDelegator, keeper)
require.True(t, got.IsOK(), "expected no error") require.True(t, got.IsOK(), "expected no error")
types.MsgCdc.MustUnmarshalBinary(got.Data, &finishTime) types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
ctx = ctx.WithBlockTime(finishTime) ctx = ctx.WithBlockTime(finishTime)
EndBlocker(ctx, keeper) EndBlocker(ctx, keeper)
@ -621,7 +622,7 @@ func TestValidatorQueue(t *testing.T) {
got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingValidator, keeper) got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingValidator, keeper)
require.True(t, got.IsOK(), "expected no error: %v", got) require.True(t, got.IsOK(), "expected no error: %v", got)
var finishTime time.Time var finishTime time.Time
types.MsgCdc.MustUnmarshalBinary(got.Data, &finishTime) types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
ctx = ctx.WithBlockTime(finishTime) ctx = ctx.WithBlockTime(finishTime)
EndBlocker(ctx, keeper) EndBlocker(ctx, keeper)
origHeader := ctx.BlockHeader() origHeader := ctx.BlockHeader()
@ -709,7 +710,7 @@ func TestUnbondingFromUnbondingValidator(t *testing.T) {
// change the ctx to Block Time one second before the validator would have unbonded // change the ctx to Block Time one second before the validator would have unbonded
var finishTime time.Time var finishTime time.Time
types.MsgCdc.MustUnmarshalBinary(got.Data, &finishTime) types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
ctx = ctx.WithBlockTime(finishTime.Add(time.Second * -1)) ctx = ctx.WithBlockTime(finishTime.Add(time.Second * -1))
// unbond the delegator from the validator // unbond the delegator from the validator
@ -1013,7 +1014,7 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
EndBlocker(ctx, keeper) EndBlocker(ctx, keeper)
// validator power should have been reduced to zero // validator power should have been reduced to zero
// ergo validator should have been removed from the store // validator should be in unbonding state
_, found = keeper.GetValidator(ctx, valA) validator, _ = keeper.GetValidator(ctx, valA)
require.False(t, found) require.Equal(t, validator.GetStatus(), sdk.Unbonding)
} }

View File

@ -163,14 +163,14 @@ func (k Keeper) GetUnbondingQueueTimeSlice(ctx sdk.Context, timestamp time.Time)
if bz == nil { if bz == nil {
return []types.DVPair{} return []types.DVPair{}
} }
k.cdc.MustUnmarshalBinary(bz, &dvPairs) k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &dvPairs)
return dvPairs return dvPairs
} }
// Sets a specific unbonding queue timeslice. // Sets a specific unbonding queue timeslice.
func (k Keeper) SetUnbondingQueueTimeSlice(ctx sdk.Context, timestamp time.Time, keys []types.DVPair) { func (k Keeper) SetUnbondingQueueTimeSlice(ctx sdk.Context, timestamp time.Time, keys []types.DVPair) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshalBinary(keys) bz := k.cdc.MustMarshalBinaryLengthPrefixed(keys)
store.Set(GetUnbondingDelegationTimeKey(timestamp), bz) store.Set(GetUnbondingDelegationTimeKey(timestamp), bz)
} }
@ -199,7 +199,7 @@ func (k Keeper) DequeueAllMatureUnbondingQueue(ctx sdk.Context, currTime time.Ti
unbondingTimesliceIterator := k.UnbondingQueueIterator(ctx, ctx.BlockHeader().Time) unbondingTimesliceIterator := k.UnbondingQueueIterator(ctx, ctx.BlockHeader().Time)
for ; unbondingTimesliceIterator.Valid(); unbondingTimesliceIterator.Next() { for ; unbondingTimesliceIterator.Valid(); unbondingTimesliceIterator.Next() {
timeslice := []types.DVPair{} timeslice := []types.DVPair{}
k.cdc.MustUnmarshalBinary(unbondingTimesliceIterator.Value(), &timeslice) k.cdc.MustUnmarshalBinaryLengthPrefixed(unbondingTimesliceIterator.Value(), &timeslice)
matureUnbonds = append(matureUnbonds, timeslice...) matureUnbonds = append(matureUnbonds, timeslice...)
store.Delete(unbondingTimesliceIterator.Key()) store.Delete(unbondingTimesliceIterator.Key())
} }
@ -300,14 +300,14 @@ func (k Keeper) GetRedelegationQueueTimeSlice(ctx sdk.Context, timestamp time.Ti
if bz == nil { if bz == nil {
return []types.DVVTriplet{} return []types.DVVTriplet{}
} }
k.cdc.MustUnmarshalBinary(bz, &dvvTriplets) k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &dvvTriplets)
return dvvTriplets return dvvTriplets
} }
// Sets a specific redelegation queue timeslice. // Sets a specific redelegation queue timeslice.
func (k Keeper) SetRedelegationQueueTimeSlice(ctx sdk.Context, timestamp time.Time, keys []types.DVVTriplet) { func (k Keeper) SetRedelegationQueueTimeSlice(ctx sdk.Context, timestamp time.Time, keys []types.DVVTriplet) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshalBinary(keys) bz := k.cdc.MustMarshalBinaryLengthPrefixed(keys)
store.Set(GetRedelegationTimeKey(timestamp), bz) store.Set(GetRedelegationTimeKey(timestamp), bz)
} }
@ -336,7 +336,7 @@ func (k Keeper) DequeueAllMatureRedelegationQueue(ctx sdk.Context, currTime time
redelegationTimesliceIterator := k.RedelegationQueueIterator(ctx, ctx.BlockHeader().Time) redelegationTimesliceIterator := k.RedelegationQueueIterator(ctx, ctx.BlockHeader().Time)
for ; redelegationTimesliceIterator.Valid(); redelegationTimesliceIterator.Next() { for ; redelegationTimesliceIterator.Valid(); redelegationTimesliceIterator.Next() {
timeslice := []types.DVVTriplet{} timeslice := []types.DVVTriplet{}
k.cdc.MustUnmarshalBinary(redelegationTimesliceIterator.Value(), &timeslice) k.cdc.MustUnmarshalBinaryLengthPrefixed(redelegationTimesliceIterator.Value(), &timeslice)
matureRedelegations = append(matureRedelegations, timeslice...) matureRedelegations = append(matureRedelegations, timeslice...)
store.Delete(redelegationTimesliceIterator.Key()) store.Delete(redelegationTimesliceIterator.Key())
} }
@ -349,6 +349,13 @@ func (k Keeper) DequeueAllMatureRedelegationQueue(ctx sdk.Context, currTime time
func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Coin, func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Coin,
validator types.Validator, subtractAccount bool) (newShares sdk.Dec, err sdk.Error) { validator types.Validator, subtractAccount bool) (newShares sdk.Dec, err sdk.Error) {
// In some situations, the exchange rate becomes invalid, e.g. if
// validator loses all tokens due to slashing. In this case,
// make all future delegations invalid.
if validator.DelegatorShareExRate().IsZero() {
return sdk.ZeroDec(), types.ErrDelegatorShareExRateInvalid(k.Codespace())
}
// Get or create the delegator delegation // Get or create the delegator delegation
delegation, found := k.GetDelegation(ctx, delAddr, validator.OperatorAddr) delegation, found := k.GetDelegation(ctx, delAddr, validator.OperatorAddr)
if !found { if !found {

View File

@ -36,7 +36,7 @@ func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, paramst
} }
// Set the validator hooks // Set the validator hooks
func (k Keeper) WithHooks(sh sdk.StakingHooks) Keeper { func (k *Keeper) SetHooks(sh sdk.StakingHooks) *Keeper {
if k.hooks != nil { if k.hooks != nil {
panic("cannot set validator hooks twice") panic("cannot set validator hooks twice")
} }
@ -60,14 +60,14 @@ func (k Keeper) GetPool(ctx sdk.Context) (pool types.Pool) {
if b == nil { if b == nil {
panic("stored pool should not have been nil") panic("stored pool should not have been nil")
} }
k.cdc.MustUnmarshalBinary(b, &pool) k.cdc.MustUnmarshalBinaryLengthPrefixed(b, &pool)
return return
} }
// set the pool // set the pool
func (k Keeper) SetPool(ctx sdk.Context, pool types.Pool) { func (k Keeper) SetPool(ctx sdk.Context, pool types.Pool) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
b := k.cdc.MustMarshalBinary(pool) b := k.cdc.MustMarshalBinaryLengthPrefixed(pool)
store.Set(PoolKey, b) store.Set(PoolKey, b)
} }
@ -80,14 +80,14 @@ func (k Keeper) GetLastTotalPower(ctx sdk.Context) (power sdk.Int) {
if b == nil { if b == nil {
return sdk.ZeroInt() return sdk.ZeroInt()
} }
k.cdc.MustUnmarshalBinary(b, &power) k.cdc.MustUnmarshalBinaryLengthPrefixed(b, &power)
return return
} }
// Set the last total validator power. // Set the last total validator power.
func (k Keeper) SetLastTotalPower(ctx sdk.Context, power sdk.Int) { func (k Keeper) SetLastTotalPower(ctx sdk.Context, power sdk.Int) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
b := k.cdc.MustMarshalBinary(power) b := k.cdc.MustMarshalBinaryLengthPrefixed(power)
store.Set(LastTotalPowerKey, b) store.Set(LastTotalPowerKey, b)
} }
@ -101,14 +101,14 @@ func (k Keeper) GetLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress)
if bz == nil { if bz == nil {
return sdk.ZeroInt() return sdk.ZeroInt()
} }
k.cdc.MustUnmarshalBinary(bz, &power) k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &power)
return return
} }
// Set the last validator power. // Set the last validator power.
func (k Keeper) SetLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress, power sdk.Int) { func (k Keeper) SetLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress, power sdk.Int) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshalBinary(power) bz := k.cdc.MustMarshalBinaryLengthPrefixed(power)
store.Set(GetLastValidatorPowerKey(operator), bz) store.Set(GetLastValidatorPowerKey(operator), bz)
} }
@ -128,13 +128,13 @@ func (k Keeper) GetIntraTxCounter(ctx sdk.Context) int16 {
return 0 return 0
} }
var counter int16 var counter int16
k.cdc.MustUnmarshalBinary(b, &counter) k.cdc.MustUnmarshalBinaryLengthPrefixed(b, &counter)
return counter return counter
} }
// set the current in-block validator operation counter // set the current in-block validator operation counter
func (k Keeper) SetIntraTxCounter(ctx sdk.Context, counter int16) { func (k Keeper) SetIntraTxCounter(ctx sdk.Context, counter int16) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshalBinary(counter) bz := k.cdc.MustMarshalBinaryLengthPrefixed(counter)
store.Set(IntraTxCounterKey, bz) store.Set(IntraTxCounterKey, bz)
} }

View File

@ -28,9 +28,31 @@ func (k Keeper) IterateValidators(ctx sdk.Context, fn func(index int64, validato
} }
// iterate through the active validator set and perform the provided function // iterate through the active validator set and perform the provided function
func (k Keeper) IterateValidatorsBonded(ctx sdk.Context, fn func(index int64, validator sdk.Validator) (stop bool)) { func (k Keeper) IterateBondedValidatorsByPower(ctx sdk.Context, fn func(index int64, validator sdk.Validator) (stop bool)) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, LastValidatorPowerKey) maxValidators := k.MaxValidators(ctx)
iterator := sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey)
defer iterator.Close()
i := int64(0)
for ; iterator.Valid() && i < int64(maxValidators); iterator.Next() {
address := iterator.Value()
validator := k.mustGetValidator(ctx, address)
if validator.Status == sdk.Bonded {
stop := fn(i, validator) // XXX is this safe will the validator unexposed fields be able to get written to?
if stop {
break
}
i++
}
}
}
// iterate through the active validator set and perform the provided function
func (k Keeper) IterateLastValidators(ctx sdk.Context, fn func(index int64, validator sdk.Validator) (stop bool)) {
iterator := k.LastValidatorsIterator(ctx)
i := int64(0) i := int64(0)
for ; iterator.Valid(); iterator.Next() { for ; iterator.Valid(); iterator.Next() {
address := AddressFromLastValidatorPowerKey(iterator.Key()) address := AddressFromLastValidatorPowerKey(iterator.Key())

View File

@ -108,12 +108,6 @@ func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeigh
pool.LooseTokens = pool.LooseTokens.Sub(tokensToBurn) pool.LooseTokens = pool.LooseTokens.Sub(tokensToBurn)
k.SetPool(ctx, pool) k.SetPool(ctx, pool)
// remove validator if it has no more tokens
if validator.DelegatorShares.IsZero() && validator.Status == sdk.Unbonded {
// if not unbonded, we must instead remove validator in EndBlocker once it finishes its unbonding period
k.RemoveValidator(ctx, validator.OperatorAddr)
}
// Log that a slash occurred! // Log that a slash occurred!
logger.Info(fmt.Sprintf( logger.Info(fmt.Sprintf(
"validator %s slashed by slash factor of %s; burned %v tokens", "validator %s slashed by slash factor of %s; burned %v tokens",
@ -236,6 +230,7 @@ func (k Keeper) slashRedelegation(ctx sdk.Context, validator types.Validator, re
if sharesToUnbond.GT(delegation.Shares) { if sharesToUnbond.GT(delegation.Shares) {
sharesToUnbond = delegation.Shares sharesToUnbond = delegation.Shares
} }
tokensToBurn, err := k.unbond(ctx, redelegation.DelegatorAddr, redelegation.ValidatorDstAddr, sharesToUnbond) tokensToBurn, err := k.unbond(ctx, redelegation.DelegatorAddr, redelegation.ValidatorDstAddr, sharesToUnbond)
if err != nil { if err != nil {
panic(fmt.Errorf("error unbonding delegator: %v", err)) panic(fmt.Errorf("error unbonding delegator: %v", err))

View File

@ -348,9 +348,9 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
keeper.ApplyAndReturnValidatorSetUpdates(ctx) keeper.ApplyAndReturnValidatorSetUpdates(ctx)
// read updated validator // read updated validator
// power decreased by 1 again, validator is out of stake // power decreased by 1 again, validator is out of stake
// ergo validator should have been removed from the store // validator should be in unbonding period
_, found = keeper.GetValidatorByConsAddr(ctx, consAddr) validator, _ = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.False(t, found) require.Equal(t, validator.GetStatus(), sdk.Unbonding)
} }
// tests Slash at a previous height with a redelegation // tests Slash at a previous height with a redelegation
@ -450,16 +450,16 @@ func TestSlashWithRedelegation(t *testing.T) {
// apply TM updates // apply TM updates
keeper.ApplyAndReturnValidatorSetUpdates(ctx) keeper.ApplyAndReturnValidatorSetUpdates(ctx)
// read updated validator // read updated validator
// validator decreased to zero power, should have been removed from the store // validator decreased to zero power, should be in unbonding period
_, found = keeper.GetValidatorByConsAddr(ctx, consAddr) validator, _ = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.False(t, found) require.Equal(t, validator.GetStatus(), sdk.Unbonding)
// slash the validator again, by 100% // slash the validator again, by 100%
// no stake remains to be slashed // no stake remains to be slashed
ctx = ctx.WithBlockHeight(12) ctx = ctx.WithBlockHeight(12)
// validator no longer in the store // validator still in unbonding period
_, found = keeper.GetValidatorByConsAddr(ctx, consAddr) validator, _ = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.False(t, found) require.Equal(t, validator.GetStatus(), sdk.Unbonding)
keeper.Slash(ctx, consAddr, 10, 10, sdk.OneDec()) keeper.Slash(ctx, consAddr, 10, 10, sdk.OneDec())
// read updating redelegation // read updating redelegation
@ -472,9 +472,9 @@ func TestSlashWithRedelegation(t *testing.T) {
// no more bonded tokens burned // no more bonded tokens burned
require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
// read updated validator // read updated validator
// power still zero, still not in the store // power still zero, still in unbonding period
_, found = keeper.GetValidatorByConsAddr(ctx, consAddr) validator, _ = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.False(t, found) require.Equal(t, validator.GetStatus(), sdk.Unbonding)
} }
// tests Slash at a previous height with both an unbonding delegation and a redelegation // tests Slash at a previous height with both an unbonding delegation and a redelegation

View File

@ -73,13 +73,13 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab
// calculate the new power bytes // calculate the new power bytes
newPower := validator.BondedTokens().RoundInt64() newPower := validator.BondedTokens().RoundInt64()
newPowerBytes := k.cdc.MustMarshalBinary(sdk.NewInt(newPower)) newPowerBytes := k.cdc.MustMarshalBinaryLengthPrefixed(sdk.NewInt(newPower))
// update the validator set if power has changed // update the validator set if power has changed
if !found || !bytes.Equal(oldPowerBytes, newPowerBytes) { if !found || !bytes.Equal(oldPowerBytes, newPowerBytes) {
updates = append(updates, validator.ABCIValidatorUpdate()) updates = append(updates, validator.ABCIValidatorUpdate())
// XXX Assert that the validator had updated its ValidatorDistInfo.FeePoolWithdrawalHeight. // Assert that the validator had updated its ValidatorDistInfo.FeePoolWithdrawalHeight.
// XXX This hook probably shouldn't exist. Maybe rethink the hook system. // This hook is extremely useful, otherwise lazy accum bugs will be difficult to solve.
if k.hooks != nil { if k.hooks != nil {
k.hooks.OnValidatorPowerDidChange(ctx, validator.ConsAddress(), valAddr) k.hooks.OnValidatorPowerDidChange(ctx, validator.ConsAddress(), valAddr)
} }
@ -108,11 +108,6 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab
// bonded to unbonding // bonded to unbonding
k.bondedToUnbonding(ctx, validator) k.bondedToUnbonding(ctx, validator)
// remove validator if it has no more tokens
if validator.Tokens.IsZero() {
k.RemoveValidator(ctx, validator.OperatorAddr)
}
// delete from the bonded validator index // delete from the bonded validator index
k.DeleteLastValidatorPower(ctx, sdk.ValAddress(valAddrBytes)) k.DeleteLastValidatorPower(ctx, sdk.ValAddress(valAddrBytes))

View File

@ -155,6 +155,7 @@ func (k Keeper) RemoveValidatorTokensAndShares(ctx sdk.Context, validator types.
// Update the tokens of an existing validator, update the validators power index key // Update the tokens of an existing validator, update the validators power index key
func (k Keeper) RemoveValidatorTokens(ctx sdk.Context, validator types.Validator, tokensToRemove sdk.Dec) types.Validator { func (k Keeper) RemoveValidatorTokens(ctx sdk.Context, validator types.Validator, tokensToRemove sdk.Dec) types.Validator {
pool := k.GetPool(ctx) pool := k.GetPool(ctx)
k.DeleteValidatorByPowerIndex(ctx, validator, pool) k.DeleteValidatorByPowerIndex(ctx, validator, pool)
validator, pool = validator.RemoveTokens(pool, tokensToRemove) validator, pool = validator.RemoveTokens(pool, tokensToRemove)
@ -189,6 +190,9 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
if !found { if !found {
return return
} }
if validator.Status != sdk.Unbonded {
panic("Cannot call RemoveValidator on bonded or unbonding validators")
}
// delete the old validator record // delete the old validator record
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
@ -261,6 +265,13 @@ func (k Keeper) GetLastValidators(ctx sdk.Context) (validators []types.Validator
return validators[:i] // trim return validators[:i] // trim
} }
// returns an iterator for the consensus validators in the last block
func (k Keeper) LastValidatorsIterator(ctx sdk.Context) (iterator sdk.Iterator) {
store := ctx.KVStore(k.storeKey)
iterator = sdk.KVStorePrefixIterator(store, LastValidatorPowerKey)
return iterator
}
// get the current group of bonded validators sorted by power-rank // get the current group of bonded validators sorted by power-rank
func (k Keeper) GetBondedValidatorsByPower(ctx sdk.Context) []types.Validator { func (k Keeper) GetBondedValidatorsByPower(ctx sdk.Context) []types.Validator {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
@ -283,6 +294,13 @@ func (k Keeper) GetBondedValidatorsByPower(ctx sdk.Context) []types.Validator {
return validators[:i] // trim return validators[:i] // trim
} }
// returns an iterator for the current validator power store
func (k Keeper) ValidatorsPowerStoreIterator(ctx sdk.Context) (iterator sdk.Iterator) {
store := ctx.KVStore(k.storeKey)
iterator = sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey)
return iterator
}
// gets a specific validator queue timeslice. A timeslice is a slice of ValAddresses corresponding to unbonding validators // gets a specific validator queue timeslice. A timeslice is a slice of ValAddresses corresponding to unbonding validators
// that expire at a certain time. // that expire at a certain time.
func (k Keeper) GetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time) (valAddrs []sdk.ValAddress) { func (k Keeper) GetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time) (valAddrs []sdk.ValAddress) {
@ -291,14 +309,14 @@ func (k Keeper) GetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time)
if bz == nil { if bz == nil {
return []sdk.ValAddress{} return []sdk.ValAddress{}
} }
k.cdc.MustUnmarshalBinary(bz, &valAddrs) k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &valAddrs)
return valAddrs return valAddrs
} }
// Sets a specific validator queue timeslice. // Sets a specific validator queue timeslice.
func (k Keeper) SetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time, keys []sdk.ValAddress) { func (k Keeper) SetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time, keys []sdk.ValAddress) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshalBinary(keys) bz := k.cdc.MustMarshalBinaryLengthPrefixed(keys)
store.Set(GetValidatorQueueTimeKey(timestamp), bz) store.Set(GetValidatorQueueTimeKey(timestamp), bz)
} }
@ -325,7 +343,7 @@ func (k Keeper) GetAllMatureValidatorQueue(ctx sdk.Context, currTime time.Time)
validatorTimesliceIterator := k.ValidatorQueueIterator(ctx, ctx.BlockHeader().Time) validatorTimesliceIterator := k.ValidatorQueueIterator(ctx, ctx.BlockHeader().Time)
for ; validatorTimesliceIterator.Valid(); validatorTimesliceIterator.Next() { for ; validatorTimesliceIterator.Valid(); validatorTimesliceIterator.Next() {
timeslice := []sdk.ValAddress{} timeslice := []sdk.ValAddress{}
k.cdc.MustUnmarshalBinary(validatorTimesliceIterator.Value(), &timeslice) k.cdc.MustUnmarshalBinaryLengthPrefixed(validatorTimesliceIterator.Value(), &timeslice)
matureValsAddrs = append(matureValsAddrs, timeslice...) matureValsAddrs = append(matureValsAddrs, timeslice...)
} }
return matureValsAddrs return matureValsAddrs
@ -337,16 +355,15 @@ func (k Keeper) UnbondAllMatureValidatorQueue(ctx sdk.Context) {
validatorTimesliceIterator := k.ValidatorQueueIterator(ctx, ctx.BlockHeader().Time) validatorTimesliceIterator := k.ValidatorQueueIterator(ctx, ctx.BlockHeader().Time)
for ; validatorTimesliceIterator.Valid(); validatorTimesliceIterator.Next() { for ; validatorTimesliceIterator.Valid(); validatorTimesliceIterator.Next() {
timeslice := []sdk.ValAddress{} timeslice := []sdk.ValAddress{}
k.cdc.MustUnmarshalBinary(validatorTimesliceIterator.Value(), &timeslice) k.cdc.MustUnmarshalBinaryLengthPrefixed(validatorTimesliceIterator.Value(), &timeslice)
for _, valAddr := range timeslice { for _, valAddr := range timeslice {
val, found := k.GetValidator(ctx, valAddr) val, found := k.GetValidator(ctx, valAddr)
if !found || val.GetStatus() != sdk.Unbonding { if !found || val.GetStatus() != sdk.Unbonding {
continue continue
} }
k.unbondingToUnbonded(ctx, val)
if val.GetDelegatorShares().IsZero() { if val.GetDelegatorShares().IsZero() {
k.RemoveValidator(ctx, val.OperatorAddr) k.RemoveValidator(ctx, val.OperatorAddr)
} else {
k.unbondingToUnbonded(ctx, val)
} }
} }
store.Delete(validatorTimesliceIterator.Key()) store.Delete(validatorTimesliceIterator.Key())

View File

@ -186,9 +186,9 @@ func TestSlashToZeroPowerRemoved(t *testing.T) {
keeper.Slash(ctx, consAddr0, 0, 100, sdk.OneDec()) keeper.Slash(ctx, consAddr0, 0, 100, sdk.OneDec())
// apply TM updates // apply TM updates
keeper.ApplyAndReturnValidatorSetUpdates(ctx) keeper.ApplyAndReturnValidatorSetUpdates(ctx)
// validator should have been deleted // validator should be unbonding
_, found := keeper.GetValidator(ctx, addrVals[0]) validator, _ = keeper.GetValidator(ctx, addrVals[0])
require.False(t, found) require.Equal(t, validator.GetStatus(), sdk.Unbonding)
} }
// This function tests UpdateValidator, GetValidator, GetLastValidators, RemoveValidator // This function tests UpdateValidator, GetValidator, GetLastValidators, RemoveValidator
@ -276,7 +276,9 @@ func TestValidatorBasics(t *testing.T) {
assert.True(ValEq(t, validators[2], resVals[2])) assert.True(ValEq(t, validators[2], resVals[2]))
// remove a record // remove a record
keeper.RemoveValidator(ctx, validators[1].OperatorAddr) validators[1].Status = sdk.Unbonded // First must set to Unbonded.
keeper.SetValidator(ctx, validators[1]) // ...
keeper.RemoveValidator(ctx, validators[1].OperatorAddr) // Now it can be removed.
_, found = keeper.GetValidator(ctx, addrVals[1]) _, found = keeper.GetValidator(ctx, addrVals[1])
require.False(t, found) require.False(t, found)
} }

View File

@ -1,6 +1,7 @@
package simulation package simulation
import ( import (
"bytes"
"fmt" "fmt"
"github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/baseapp"
@ -10,6 +11,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/distribution" "github.com/cosmos/cosmos-sdk/x/distribution"
"github.com/cosmos/cosmos-sdk/x/mock/simulation" "github.com/cosmos/cosmos-sdk/x/mock/simulation"
"github.com/cosmos/cosmos-sdk/x/stake" "github.com/cosmos/cosmos-sdk/x/stake"
"github.com/cosmos/cosmos-sdk/x/stake/keeper"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
) )
@ -24,10 +26,12 @@ func AllInvariants(ck bank.Keeper, k stake.Keeper,
if err != nil { if err != nil {
return err return err
} }
err = PositivePowerInvariant(k)(app) err = PositivePowerInvariant(k)(app)
if err != nil { if err != nil {
return err return err
} }
err = ValidatorSetInvariant(k)(app) err = ValidatorSetInvariant(k)(app)
return err return err
} }
@ -100,19 +104,29 @@ func SupplyInvariants(ck bank.Keeper, k stake.Keeper,
} }
} }
// PositivePowerInvariant checks that all stored validators have > 0 power // PositivePowerInvariant checks that all stored validators have > 0 power.
func PositivePowerInvariant(k stake.Keeper) simulation.Invariant { func PositivePowerInvariant(k stake.Keeper) simulation.Invariant {
return func(app *baseapp.BaseApp) error { return func(app *baseapp.BaseApp) error {
ctx := app.NewContext(false, abci.Header{}) ctx := app.NewContext(false, abci.Header{})
var err error
k.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) bool { iterator := k.ValidatorsPowerStoreIterator(ctx)
if !validator.GetPower().GT(sdk.ZeroDec()) { pool := k.GetPool(ctx)
err = fmt.Errorf("validator with non-positive power stored. (pubkey %v)", validator.GetConsPubKey())
return true for ; iterator.Valid(); iterator.Next() {
validator, found := k.GetValidator(ctx, iterator.Value())
if !found {
panic(fmt.Sprintf("validator record not found for address: %X\n", iterator.Value()))
} }
return false
}) powerKey := keeper.GetValidatorsByPowerIndexKey(validator, pool)
return err
if !bytes.Equal(iterator.Key(), powerKey) {
return fmt.Errorf("power store invariance:\n\tvalidator.Power: %v"+
"\n\tkey should be: %v\n\tkey in store: %v", validator.GetPower(), powerKey, iterator.Key())
}
}
iterator.Close()
return nil
} }
} }

View File

@ -47,7 +47,7 @@ func MustMarshalDelegation(cdc *codec.Codec, delegation Delegation) []byte {
delegation.Shares, delegation.Shares,
delegation.Height, delegation.Height,
} }
return cdc.MustMarshalBinary(val) return cdc.MustMarshalBinaryLengthPrefixed(val)
} }
// return the delegation without fields contained within the key for the store // return the delegation without fields contained within the key for the store
@ -62,7 +62,7 @@ func MustUnmarshalDelegation(cdc *codec.Codec, key, value []byte) Delegation {
// return the delegation without fields contained within the key for the store // return the delegation without fields contained within the key for the store
func UnmarshalDelegation(cdc *codec.Codec, key, value []byte) (delegation Delegation, err error) { func UnmarshalDelegation(cdc *codec.Codec, key, value []byte) (delegation Delegation, err error) {
var storeValue delegationValue var storeValue delegationValue
err = cdc.UnmarshalBinary(value, &storeValue) err = cdc.UnmarshalBinaryLengthPrefixed(value, &storeValue)
if err != nil { if err != nil {
err = fmt.Errorf("%v: %v", ErrNoDelegation(DefaultCodespace).Data(), err) err = fmt.Errorf("%v: %v", ErrNoDelegation(DefaultCodespace).Data(), err)
return return
@ -139,7 +139,7 @@ func MustMarshalUBD(cdc *codec.Codec, ubd UnbondingDelegation) []byte {
ubd.InitialBalance, ubd.InitialBalance,
ubd.Balance, ubd.Balance,
} }
return cdc.MustMarshalBinary(val) return cdc.MustMarshalBinaryLengthPrefixed(val)
} }
// unmarshal a unbonding delegation from a store key and value // unmarshal a unbonding delegation from a store key and value
@ -154,7 +154,7 @@ func MustUnmarshalUBD(cdc *codec.Codec, key, value []byte) UnbondingDelegation {
// unmarshal a unbonding delegation from a store key and value // unmarshal a unbonding delegation from a store key and value
func UnmarshalUBD(cdc *codec.Codec, key, value []byte) (ubd UnbondingDelegation, err error) { func UnmarshalUBD(cdc *codec.Codec, key, value []byte) (ubd UnbondingDelegation, err error) {
var storeValue ubdValue var storeValue ubdValue
err = cdc.UnmarshalBinary(value, &storeValue) err = cdc.UnmarshalBinaryLengthPrefixed(value, &storeValue)
if err != nil { if err != nil {
return return
} }
@ -179,8 +179,8 @@ func UnmarshalUBD(cdc *codec.Codec, key, value []byte) (ubd UnbondingDelegation,
// nolint // nolint
func (d UnbondingDelegation) Equal(d2 UnbondingDelegation) bool { func (d UnbondingDelegation) Equal(d2 UnbondingDelegation) bool {
bz1 := MsgCdc.MustMarshalBinary(&d) bz1 := MsgCdc.MustMarshalBinaryLengthPrefixed(&d)
bz2 := MsgCdc.MustMarshalBinary(&d2) bz2 := MsgCdc.MustMarshalBinaryLengthPrefixed(&d2)
return bytes.Equal(bz1, bz2) return bytes.Equal(bz1, bz2)
} }
@ -231,7 +231,7 @@ func MustMarshalRED(cdc *codec.Codec, red Redelegation) []byte {
red.SharesSrc, red.SharesSrc,
red.SharesDst, red.SharesDst,
} }
return cdc.MustMarshalBinary(val) return cdc.MustMarshalBinaryLengthPrefixed(val)
} }
// unmarshal a redelegation from a store key and value // unmarshal a redelegation from a store key and value
@ -246,7 +246,7 @@ func MustUnmarshalRED(cdc *codec.Codec, key, value []byte) Redelegation {
// unmarshal a redelegation from a store key and value // unmarshal a redelegation from a store key and value
func UnmarshalRED(cdc *codec.Codec, key, value []byte) (red Redelegation, err error) { func UnmarshalRED(cdc *codec.Codec, key, value []byte) (red Redelegation, err error) {
var storeValue redValue var storeValue redValue
err = cdc.UnmarshalBinary(value, &storeValue) err = cdc.UnmarshalBinaryLengthPrefixed(value, &storeValue)
if err != nil { if err != nil {
return return
} }
@ -275,8 +275,8 @@ func UnmarshalRED(cdc *codec.Codec, key, value []byte) (red Redelegation, err er
// nolint // nolint
func (d Redelegation) Equal(d2 Redelegation) bool { func (d Redelegation) Equal(d2 Redelegation) bool {
bz1 := MsgCdc.MustMarshalBinary(&d) bz1 := MsgCdc.MustMarshalBinaryLengthPrefixed(&d)
bz2 := MsgCdc.MustMarshalBinary(&d2) bz2 := MsgCdc.MustMarshalBinaryLengthPrefixed(&d2)
return bytes.Equal(bz1, bz2) return bytes.Equal(bz1, bz2)
} }

View File

@ -173,6 +173,11 @@ func ErrConflictingRedelegation(codespace sdk.CodespaceType) sdk.Error {
"conflicting redelegation from this source validator to this dest validator already exists, you must wait for it to finish") "conflicting redelegation from this source validator to this dest validator already exists, you must wait for it to finish")
} }
func ErrDelegatorShareExRateInvalid(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidDelegation,
"cannot delegate to validators with invalid (zero) ex-rate")
}
func ErrBothShareMsgsGiven(codespace sdk.CodespaceType) sdk.Error { func ErrBothShareMsgsGiven(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInput, "both shares amount and shares percent provided") return sdk.NewError(codespace, CodeInvalidInput, "both shares amount and shares percent provided")
} }

View File

@ -49,8 +49,8 @@ func (p *Params) KeyValuePairs() params.KeyValuePairs {
// Equal returns a boolean determining if two Param types are identical. // Equal returns a boolean determining if two Param types are identical.
func (p Params) Equal(p2 Params) bool { func (p Params) Equal(p2 Params) bool {
bz1 := MsgCdc.MustMarshalBinary(&p) bz1 := MsgCdc.MustMarshalBinaryLengthPrefixed(&p)
bz2 := MsgCdc.MustMarshalBinary(&p2) bz2 := MsgCdc.MustMarshalBinaryLengthPrefixed(&p2)
return bytes.Equal(bz1, bz2) return bytes.Equal(bz1, bz2)
} }
@ -85,7 +85,7 @@ func MustUnmarshalParams(cdc *codec.Codec, value []byte) Params {
// unmarshal the current staking params value from store key // unmarshal the current staking params value from store key
func UnmarshalParams(cdc *codec.Codec, value []byte) (params Params, err error) { func UnmarshalParams(cdc *codec.Codec, value []byte) (params Params, err error) {
err = cdc.UnmarshalBinary(value, &params) err = cdc.UnmarshalBinaryLengthPrefixed(value, &params)
if err != nil { if err != nil {
return return
} }

Some files were not shown because too many files have changed in this diff Show More