Merge pull request #834 from cosmos/release/v0.15.0

Release/v0.15.0
This commit is contained in:
Ethan Buchman 2018-04-29 23:12:45 -04:00 committed by GitHub
commit 07842b6876
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
72 changed files with 1036 additions and 700 deletions

5
.dockerignore Normal file
View File

@ -0,0 +1,5 @@
Dockerfile
Vagrantfile
build/
coverage.txt

View File

@ -1,5 +1,23 @@
# Changelog # Changelog
## 0.15.0 (April 29, 2018)
FEATURES:
* Add CacheContext
* Add auto sequencing to client
* Add FeeHandler to ante handler
BREAKING CHANGES
* Remove go-wire, use go-amino
* [store] Add `SubspaceIterator` and `ReverseSubspaceIterator` to `KVStore` interface
* [basecoin] NewBasecoinApp takes a `dbm.DB` and uses namespaced DBs for substores
BUG FIXES
* MountStoreWithDB without providing a custom store works.
## 0.14.1 (April 9, 2018) ## 0.14.1 (April 9, 2018)
BUG FIXES BUG FIXES

View File

@ -1,28 +1,34 @@
FROM alpine:3.5 # Simple usage with a mounted data directory:
# > docker build -t gaia .
# > docker run -v $HOME/.gaiad:/root/.gaiad gaia init
# > docker run -v $HOME/.gaiad:/root/.gaiad gaia start
# BCHOME is where your genesis.json, key.json and other files including state are stored. FROM alpine:edge
ENV BCHOME /basecoin
# Create a basecoin user and group first so the IDs get set the same way, even # Set up dependencies
# as the rest of this may change over time. ENV PACKAGES go glide make git libc-dev bash
RUN addgroup basecoin && \
adduser -S -G basecoin basecoin
RUN mkdir -p $BCHOME && \ # Set up GOPATH & PATH
chown -R basecoin:basecoin $BCHOME
WORKDIR $BCHOME
# Expose the basecoin home directory as a volume since there's mutable state in there. ENV GOPATH /root/go
VOLUME $BCHOME ENV BASE_PATH $GOPATH/src/github.com/cosmos
ENV REPO_PATH $BASE_PATH/cosmos-sdk
ENV WORKDIR /cosmos/
ENV PATH $GOPATH/bin:$PATH
# jq and curl used for extracting `pub_key` from private validator while # Link expected Go repo path
# deploying tendermint with Kubernetes. It is nice to have bash so the users
# could execute bash commands.
RUN apk add --no-cache bash curl jq
COPY basecoin /usr/bin/basecoin RUN mkdir -p $WORKDIR $GOPATH/pkg $ $GOPATH/bin $BASE_PATH
ENTRYPOINT ["basecoin"] # Add source files
# By default you will get the basecoin with local MerkleEyes and in-proc Tendermint. ADD . $REPO_PATH
CMD ["start", "--dir=${BCHOME}"]
# Install minimum necessary dependencies, build Cosmos SDK, remove packages
RUN apk add --no-cache $PACKAGES && \
cd $REPO_PATH && make get_tools && make get_vendor_deps && make all && make install && \
apk del $PACKAGES
# Set entrypoint
ENTRYPOINT ["gaiad"]

37
Gopkg.lock generated
View File

@ -215,8 +215,8 @@
[[projects]] [[projects]]
name = "github.com/spf13/pflag" name = "github.com/spf13/pflag"
packages = ["."] packages = ["."]
revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66" revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
version = "v1.0.0" version = "v1.0.1"
[[projects]] [[projects]]
name = "github.com/spf13/viper" name = "github.com/spf13/viper"
@ -274,6 +274,12 @@
] ]
revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057" revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057"
[[projects]]
name = "github.com/tendermint/go-amino"
packages = ["."]
revision = "42246108ff925a457fb709475070a03dfd3e2b5c"
version = "0.9.6"
[[projects]] [[projects]]
name = "github.com/tendermint/go-crypto" name = "github.com/tendermint/go-crypto"
packages = [ packages = [
@ -283,17 +289,13 @@
"keys/words", "keys/words",
"keys/words/wordlist" "keys/words/wordlist"
] ]
revision = "c3e19f3ea26f5c3357e0bcbb799b0761ef923755" revision = "915416979bf70efa4bcbf1c6cd5d64c5fff9fc19"
version = "v0.5.0" version = "v0.6.2"
[[projects]] [[projects]]
name = "github.com/tendermint/go-wire" name = "github.com/tendermint/go-wire"
packages = [ packages = ["."]
".",
"data"
]
revision = "fa721242b042ecd4c6ed1a934ee740db4f74e45c" revision = "fa721242b042ecd4c6ed1a934ee740db4f74e45c"
source = "github.com/tendermint/go-amino"
version = "v0.7.3" version = "v0.7.3"
[[projects]] [[projects]]
@ -338,11 +340,10 @@
"state/txindex/null", "state/txindex/null",
"types", "types",
"types/priv_validator", "types/priv_validator",
"version", "version"
"wire"
] ]
revision = "4930b61a381b9fb9bc530eb5deb56ea6429a1c3a" revision = "d0beaba7e8a5652506a34b5fab299cc2dc274c02"
version = "v0.18.0" version = "v0.19.0"
[[projects]] [[projects]]
name = "github.com/tendermint/tmlibs" name = "github.com/tendermint/tmlibs"
@ -359,8 +360,8 @@
"pubsub", "pubsub",
"pubsub/query" "pubsub/query"
] ]
revision = "2e24b64fc121dcdf1cabceab8dc2f7257675483c" revision = "737154202faf75c70437f59ba5303f2eb09f5636"
version = "v0.8.1" version = "0.8.2-rc1"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -376,7 +377,7 @@
"ripemd160", "ripemd160",
"salsa20/salsa" "salsa20/salsa"
] ]
revision = "b2aa35443fbc700ab74c586ae79b81c171851023" revision = "d6449816ce06963d9d136eee5a56fca5b0616e7e"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -423,7 +424,7 @@
branch = "master" branch = "master"
name = "google.golang.org/genproto" name = "google.golang.org/genproto"
packages = ["googleapis/rpc/status"] packages = ["googleapis/rpc/status"]
revision = "ce84044298496ef4b54b4a0a0909ba593cc60e30" revision = "51d0944304c3cbce4afe9e5247e21100037bff78"
[[projects]] [[projects]]
name = "google.golang.org/grpc" name = "google.golang.org/grpc"
@ -458,6 +459,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "669e58d0c4eb48e506f1abc66119c2f21b6600d4e08e8875ac83567b5c721565" inputs-digest = "b6b2d696a242e715ddb8b25c93b3c8f7e7cabc9292eab29dffe935eddbd35fb8"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View File

@ -53,29 +53,28 @@
version = "~1.2.1" version = "~1.2.1"
[[constraint]] [[constraint]]
version = "~0.10.2"
name = "github.com/tendermint/abci" name = "github.com/tendermint/abci"
version = "~0.10.3"
[[constraint]] [[constraint]]
version = "~0.5.0"
name = "github.com/tendermint/go-crypto" name = "github.com/tendermint/go-crypto"
version = "~0.6.2"
[[constraint]] [[constraint]]
version = "~0.7.3" name = "github.com/tendermint/go-amino"
source = "github.com/tendermint/go-amino" version = "~0.9.6"
name = "github.com/tendermint/go-wire"
[[constraint]] [[constraint]]
version = "~0.7.0"
name = "github.com/tendermint/iavl" name = "github.com/tendermint/iavl"
version = "~0.7.0"
[[constraint]] [[constraint]]
version = "~0.18.0"
name = "github.com/tendermint/tendermint" name = "github.com/tendermint/tendermint"
version = "0.19.0"
[[override]] [[override]]
version = "~0.8.1"
name = "github.com/tendermint/tmlibs" name = "github.com/tendermint/tmlibs"
version = "~0.8.2-rc1"
[prune] [prune]
go-tests = true go-tests = true

View File

@ -1,7 +1,6 @@
package baseapp package baseapp
import ( import (
"encoding/json"
"fmt" "fmt"
"runtime/debug" "runtime/debug"
@ -72,21 +71,20 @@ func (app *BaseApp) Name() string {
} }
// Mount a store to the provided key in the BaseApp multistore // Mount a store to the provided key in the BaseApp multistore
// Broken until #532 is implemented.
func (app *BaseApp) MountStoresIAVL(keys ...*sdk.KVStoreKey) { func (app *BaseApp) MountStoresIAVL(keys ...*sdk.KVStoreKey) {
for _, key := range keys { for _, key := range keys {
app.MountStore(key, sdk.StoreTypeIAVL) app.MountStore(key, sdk.StoreTypeIAVL)
} }
} }
// Mount a store to the provided key in the BaseApp multistore // Mount a store to the provided key in the BaseApp multistore, using a specified DB
func (app *BaseApp) MountStoreWithDB(key sdk.StoreKey, typ sdk.StoreType, db dbm.DB) { func (app *BaseApp) MountStoreWithDB(key sdk.StoreKey, typ sdk.StoreType, db dbm.DB) {
app.cms.MountStoreWithDB(key, typ, db) app.cms.MountStoreWithDB(key, typ, db)
} }
// Mount a store to the provided key in the BaseApp multistore // Mount a store to the provided key in the BaseApp multistore, using the default DB
func (app *BaseApp) MountStore(key sdk.StoreKey, typ sdk.StoreType) { func (app *BaseApp) MountStore(key sdk.StoreKey, typ sdk.StoreType) {
app.cms.MountStoreWithDB(key, typ, app.db) app.cms.MountStoreWithDB(key, typ, nil)
} }
// nolint - Set functions // nolint - Set functions
@ -241,14 +239,6 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC
app.setDeliverState(abci.Header{}) app.setDeliverState(abci.Header{})
app.initChainer(app.deliverState.ctx, req) // no error app.initChainer(app.deliverState.ctx, req) // no error
// Initialize module genesis state
genesisState := new(map[string]json.RawMessage)
err := json.Unmarshal(req.AppStateBytes, genesisState)
if err != nil {
// TODO Return something intelligent
panic(err)
}
// NOTE: we don't commit, but BeginBlock for block 1 // NOTE: we don't commit, but BeginBlock for block 1
// starts from this deliverState // starts from this deliverState

View File

@ -35,15 +35,12 @@ func TestMountStores(t *testing.T) {
// make some cap keys // make some cap keys
capKey1 := sdk.NewKVStoreKey("key1") capKey1 := sdk.NewKVStoreKey("key1")
db1 := dbm.NewMemDB()
capKey2 := sdk.NewKVStoreKey("key2") capKey2 := sdk.NewKVStoreKey("key2")
db2 := dbm.NewMemDB()
// no stores are mounted // no stores are mounted
assert.Panics(t, func() { app.LoadLatestVersion(capKey1) }) assert.Panics(t, func() { app.LoadLatestVersion(capKey1) })
app.MountStoreWithDB(capKey1, sdk.StoreTypeIAVL, db1) app.MountStoresIAVL(capKey1, capKey2)
app.MountStoreWithDB(capKey2, sdk.StoreTypeIAVL, db2)
// stores are mounted // stores are mounted
err := app.LoadLatestVersion(capKey1) err := app.LoadLatestVersion(capKey1)
@ -155,11 +152,8 @@ func TestInitChainer(t *testing.T) {
// NOTE/TODO: mounting multiple stores is broken // NOTE/TODO: mounting multiple stores is broken
// see https://github.com/cosmos/cosmos-sdk/issues/532 // see https://github.com/cosmos/cosmos-sdk/issues/532
capKey := sdk.NewKVStoreKey("main") capKey := sdk.NewKVStoreKey("main")
db1 := dbm.NewMemDB()
capKey2 := sdk.NewKVStoreKey("key2") capKey2 := sdk.NewKVStoreKey("key2")
db2 := dbm.NewMemDB() app.MountStoresIAVL(capKey, capKey2)
app.MountStoreWithDB(capKey, sdk.StoreTypeIAVL, db1)
app.MountStoreWithDB(capKey2, sdk.StoreTypeIAVL, db2)
err := app.LoadLatestVersion(capKey) // needed to make stores non-nil err := app.LoadLatestVersion(capKey) // needed to make stores non-nil
assert.Nil(t, err) assert.Nil(t, err)
@ -191,8 +185,7 @@ func TestInitChainer(t *testing.T) {
// reload app // reload app
app = NewBaseApp(name, logger, db) app = NewBaseApp(name, logger, db)
app.MountStoreWithDB(capKey, sdk.StoreTypeIAVL, db1) app.MountStoresIAVL(capKey, capKey2)
app.MountStoreWithDB(capKey2, sdk.StoreTypeIAVL, db2)
err = app.LoadLatestVersion(capKey) // needed to make stores non-nil err = app.LoadLatestVersion(capKey) // needed to make stores non-nil
assert.Nil(t, err) assert.Nil(t, err)
app.SetInitChainer(initChainer) app.SetInitChainer(initChainer)
@ -432,7 +425,7 @@ func makePubKey(secret string) crypto.PubKey {
func makePrivKey(secret string) crypto.PrivKey { func makePrivKey(secret string) crypto.PrivKey {
privKey := crypto.GenPrivKeyEd25519FromSecret([]byte(secret)) privKey := crypto.GenPrivKeyEd25519FromSecret([]byte(secret))
return privKey.Wrap() return privKey
} }
func secret(index int) string { func secret(index int) string {

View File

@ -1,27 +1,72 @@
package context package context
import ( import (
"fmt"
"github.com/spf13/viper" "github.com/spf13/viper"
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
rpcclient "github.com/tendermint/tendermint/rpc/client" rpcclient "github.com/tendermint/tendermint/rpc/client"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/core" "github.com/cosmos/cosmos-sdk/client/core"
) )
// NewCoreContextFromViper - return a new context with parameters from the command line
func NewCoreContextFromViper() core.CoreContext { func NewCoreContextFromViper() core.CoreContext {
nodeURI := viper.GetString(client.FlagNode) nodeURI := viper.GetString(client.FlagNode)
var rpc rpcclient.Client var rpc rpcclient.Client
if nodeURI != "" { if nodeURI != "" {
rpc = rpcclient.NewHTTP(nodeURI, "/websocket") rpc = rpcclient.NewHTTP(nodeURI, "/websocket")
} }
chainID := viper.GetString(client.FlagChainID)
// if chain ID is not specified manually, read default chain ID
if chainID == "" {
def, err := defaultChainID()
if err != nil {
chainID = def
}
}
return core.CoreContext{ return core.CoreContext{
ChainID: viper.GetString(client.FlagChainID), ChainID: chainID,
Height: viper.GetInt64(client.FlagHeight), Height: viper.GetInt64(client.FlagHeight),
TrustNode: viper.GetBool(client.FlagTrustNode), TrustNode: viper.GetBool(client.FlagTrustNode),
FromAddressName: viper.GetString(client.FlagName), FromAddressName: viper.GetString(client.FlagName),
NodeURI: nodeURI, NodeURI: nodeURI,
Sequence: viper.GetInt64(client.FlagSequence), Sequence: viper.GetInt64(client.FlagSequence),
Client: rpc, Client: rpc,
Decoder: nil,
AccountStore: "main",
} }
} }
// read chain ID from genesis file, if present
func defaultChainID() (string, error) {
cfg, err := tcmd.ParseConfig()
if err != nil {
return "", err
}
doc, err := tmtypes.GenesisDocFromFile(cfg.GenesisFile())
if err != nil {
return "", err
}
return doc.ChainID, nil
}
// EnsureSequence - automatically set sequence number if none provided
func EnsureSequence(ctx core.CoreContext) (core.CoreContext, error) {
if viper.IsSet(client.FlagSequence) {
return ctx, nil
}
from, err := ctx.GetFromAddress()
if err != nil {
return ctx, err
}
seq, err := ctx.NextSequence(from)
if err != nil {
return ctx, err
}
fmt.Printf("Defaulting to next sequence number: %d\n", seq)
ctx = ctx.WithSequence(seq)
return ctx, nil
}

View File

@ -2,6 +2,8 @@ package core
import ( import (
rpcclient "github.com/tendermint/tendermint/rpc/client" rpcclient "github.com/tendermint/tendermint/rpc/client"
sdk "github.com/cosmos/cosmos-sdk/types"
) )
type CoreContext struct { type CoreContext struct {
@ -12,39 +14,61 @@ type CoreContext struct {
FromAddressName string FromAddressName string
Sequence int64 Sequence int64
Client rpcclient.Client Client rpcclient.Client
Decoder sdk.AccountDecoder
AccountStore string
} }
// WithChainID - return a copy of the context with an updated chainID
func (c CoreContext) WithChainID(chainID string) CoreContext { func (c CoreContext) WithChainID(chainID string) CoreContext {
c.ChainID = chainID c.ChainID = chainID
return c return c
} }
// WithHeight - return a copy of the context with an updated height
func (c CoreContext) WithHeight(height int64) CoreContext { func (c CoreContext) WithHeight(height int64) CoreContext {
c.Height = height c.Height = height
return c return c
} }
// WithTrustNode - return a copy of the context with an updated TrustNode flag
func (c CoreContext) WithTrustNode(trustNode bool) CoreContext { func (c CoreContext) WithTrustNode(trustNode bool) CoreContext {
c.TrustNode = trustNode c.TrustNode = trustNode
return c return c
} }
// WithNodeURI - return a copy of the context with an updated node URI
func (c CoreContext) WithNodeURI(nodeURI string) CoreContext { func (c CoreContext) WithNodeURI(nodeURI string) CoreContext {
c.NodeURI = nodeURI c.NodeURI = nodeURI
c.Client = rpcclient.NewHTTP(nodeURI, "/websocket")
return c return c
} }
// WithFromAddressName - return a copy of the context with an updated from address
func (c CoreContext) WithFromAddressName(fromAddressName string) CoreContext { func (c CoreContext) WithFromAddressName(fromAddressName string) CoreContext {
c.FromAddressName = fromAddressName c.FromAddressName = fromAddressName
return c return c
} }
// WithSequence - return a copy of the context with an updated sequence number
func (c CoreContext) WithSequence(sequence int64) CoreContext { func (c CoreContext) WithSequence(sequence int64) CoreContext {
c.Sequence = sequence c.Sequence = sequence
return c return c
} }
// WithClient - return a copy of the context with an updated RPC client instance
func (c CoreContext) WithClient(client rpcclient.Client) CoreContext { func (c CoreContext) WithClient(client rpcclient.Client) CoreContext {
c.Client = client c.Client = client
return c return c
} }
// WithDecoder - return a copy of the context with an updated Decoder
func (c CoreContext) WithDecoder(decoder sdk.AccountDecoder) CoreContext {
c.Decoder = decoder
return c
}
// WithAccountStore - return a copy of the context with an updated AccountStore
func (c CoreContext) WithAccountStore(accountStore string) CoreContext {
c.AccountStore = accountStore
return c
}

View File

@ -91,6 +91,9 @@ func (ctx CoreContext) SignAndBuild(name, passphrase string, msg sdk.Msg, cdc *w
// build the Sign Messsage from the Standard Message // build the Sign Messsage from the Standard Message
chainID := ctx.ChainID chainID := ctx.ChainID
if chainID == "" {
return nil, errors.Errorf("Chain ID required but not specified")
}
sequence := ctx.Sequence sequence := ctx.Sequence
signMsg := sdk.StdSignMsg{ signMsg := sdk.StdSignMsg{
ChainID: chainID, ChainID: chainID,
@ -137,6 +140,25 @@ func (ctx CoreContext) SignBuildBroadcast(name string, msg sdk.Msg, cdc *wire.Co
return ctx.BroadcastTx(txBytes) return ctx.BroadcastTx(txBytes)
} }
// get the next sequence for the account address
func (c CoreContext) NextSequence(address []byte) (int64, error) {
if c.Decoder == nil {
return 0, errors.New("AccountDecoder required but not provided")
}
res, err := c.Query(address, c.AccountStore)
if err != nil {
return 0, err
}
account, err := c.Decoder(res)
if err != nil {
panic(err)
}
return account.GetSequence(), nil
}
// get passphrase from std input // get passphrase from std input
func (ctx CoreContext) GetPassphraseFromStdin(name string) (pass string, err error) { func (ctx CoreContext) GetPassphraseFromStdin(name string) (pass string, err error) {
buf := client.BufferStdin() buf := client.BufferStdin()

View File

@ -7,6 +7,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"time"
cmn "github.com/tendermint/tmlibs/common" cmn "github.com/tendermint/tmlibs/common"
@ -21,11 +22,15 @@ func waitForRPC() {
laddr := GetConfig().RPC.ListenAddress laddr := GetConfig().RPC.ListenAddress
fmt.Println("LADDR", laddr) fmt.Println("LADDR", laddr)
client := rpcclient.NewJSONRPCClient(laddr) client := rpcclient.NewJSONRPCClient(laddr)
ctypes.RegisterAmino(client.Codec())
result := new(ctypes.ResultStatus) result := new(ctypes.ResultStatus)
for { for {
_, err := client.Call("status", map[string]interface{}{}, result) _, err := client.Call("status", map[string]interface{}{}, result)
if err == nil { if err == nil {
return return
} else {
fmt.Println("error", err)
time.Sleep(time.Millisecond)
} }
} }
} }

View File

@ -25,6 +25,7 @@ import (
ctypes "github.com/tendermint/tendermint/rpc/core/types" ctypes "github.com/tendermint/tendermint/rpc/core/types"
tmrpc "github.com/tendermint/tendermint/rpc/lib/server" tmrpc "github.com/tendermint/tendermint/rpc/lib/server"
tmtypes "github.com/tendermint/tendermint/types" tmtypes "github.com/tendermint/tendermint/types"
pvm "github.com/tendermint/tendermint/types/priv_validator"
"github.com/tendermint/tmlibs/cli" "github.com/tendermint/tmlibs/cli"
dbm "github.com/tendermint/tmlibs/db" dbm "github.com/tendermint/tmlibs/db"
"github.com/tendermint/tmlibs/log" "github.com/tendermint/tmlibs/log"
@ -34,8 +35,6 @@ import (
bapp "github.com/cosmos/cosmos-sdk/examples/basecoin/app" bapp "github.com/cosmos/cosmos-sdk/examples/basecoin/app"
btypes "github.com/cosmos/cosmos-sdk/examples/basecoin/types" btypes "github.com/cosmos/cosmos-sdk/examples/basecoin/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/auth"
) )
var ( var (
@ -89,7 +88,7 @@ func TestKeys(t *testing.T) {
res, body = request(t, port, "GET", "/keys", nil) res, body = request(t, port, "GET", "/keys", nil)
require.Equal(t, http.StatusOK, res.StatusCode, body) require.Equal(t, http.StatusOK, res.StatusCode, body)
var m [2]keys.KeyOutput var m [2]keys.KeyOutput
err = json.Unmarshal([]byte(body), &m) err = cdc.UnmarshalJSON([]byte(body), &m)
require.Nil(t, err) require.Nil(t, err)
assert.Equal(t, m[0].Name, name, "Did not serve keys name correctly") assert.Equal(t, m[0].Name, name, "Did not serve keys name correctly")
@ -102,7 +101,7 @@ func TestKeys(t *testing.T) {
res, body = request(t, port, "GET", keyEndpoint, nil) res, body = request(t, port, "GET", keyEndpoint, nil)
require.Equal(t, http.StatusOK, res.StatusCode, body) require.Equal(t, http.StatusOK, res.StatusCode, body)
var m2 keys.KeyOutput var m2 keys.KeyOutput
err = json.Unmarshal([]byte(body), &m2) err = cdc.UnmarshalJSON([]byte(body), &m2)
require.Nil(t, err) require.Nil(t, err)
assert.Equal(t, newName, m2.Name, "Did not serve keys name correctly") assert.Equal(t, newName, m2.Name, "Did not serve keys name correctly")
@ -142,7 +141,7 @@ func TestNodeStatus(t *testing.T) {
require.Equal(t, http.StatusOK, res.StatusCode, body) require.Equal(t, http.StatusOK, res.StatusCode, body)
var nodeInfo p2p.NodeInfo var nodeInfo p2p.NodeInfo
err := json.Unmarshal([]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")
assert.NotEqual(t, p2p.NodeInfo{}, nodeInfo, "res: %v", res) assert.NotEqual(t, p2p.NodeInfo{}, nodeInfo, "res: %v", res)
@ -165,7 +164,7 @@ func TestBlock(t *testing.T) {
res, body := request(t, port, "GET", "/blocks/latest", nil) res, body := request(t, port, "GET", "/blocks/latest", nil)
require.Equal(t, http.StatusOK, res.StatusCode, body) require.Equal(t, http.StatusOK, res.StatusCode, body)
err := json.Unmarshal([]byte(body), &resultBlock) err := cdc.UnmarshalJSON([]byte(body), &resultBlock)
require.Nil(t, err, "Couldn't parse block") require.Nil(t, err, "Couldn't parse block")
assert.NotEqual(t, ctypes.ResultBlock{}, resultBlock) assert.NotEqual(t, ctypes.ResultBlock{}, resultBlock)
@ -193,7 +192,7 @@ func TestValidators(t *testing.T) {
res, body := request(t, port, "GET", "/validatorsets/latest", nil) res, body := request(t, port, "GET", "/validatorsets/latest", nil)
require.Equal(t, http.StatusOK, res.StatusCode, body) require.Equal(t, http.StatusOK, res.StatusCode, body)
err := json.Unmarshal([]byte(body), &resultVals) err := cdc.UnmarshalJSON([]byte(body), &resultVals)
require.Nil(t, err, "Couldn't parse validatorset") require.Nil(t, err, "Couldn't parse validatorset")
assert.NotEqual(t, ctypes.ResultValidators{}, resultVals) assert.NotEqual(t, ctypes.ResultValidators{}, resultVals)
@ -203,7 +202,7 @@ func TestValidators(t *testing.T) {
res, body = request(t, port, "GET", "/validatorsets/1", nil) res, body = request(t, port, "GET", "/validatorsets/1", nil)
require.Equal(t, http.StatusOK, res.StatusCode, body) require.Equal(t, http.StatusOK, res.StatusCode, body)
err = json.Unmarshal([]byte(body), &resultVals) err = cdc.UnmarshalJSON([]byte(body), &resultVals)
require.Nil(t, err, "Couldn't parse validatorset") require.Nil(t, err, "Couldn't parse validatorset")
assert.NotEqual(t, ctypes.ResultValidators{}, resultVals) assert.NotEqual(t, ctypes.ResultValidators{}, resultVals)
@ -220,6 +219,9 @@ func TestCoinSend(t *testing.T) {
res, body := request(t, port, "GET", "/accounts/8FA6AB57AD6870F6B5B2E57735F38F2F30E73CB6", nil) res, body := request(t, port, "GET", "/accounts/8FA6AB57AD6870F6B5B2E57735F38F2F30E73CB6", nil)
require.Equal(t, http.StatusNoContent, res.StatusCode, body) require.Equal(t, http.StatusNoContent, res.StatusCode, body)
acc := getAccount(t, sendAddr)
initialBalance := acc.GetCoins()
// create TX // create TX
receiveAddr, resultTx := doSend(t, port, seed) receiveAddr, resultTx := doSend(t, port, seed)
waitForHeight(resultTx.Height + 1) waitForHeight(resultTx.Height + 1)
@ -229,24 +231,15 @@ func TestCoinSend(t *testing.T) {
assert.Equal(t, uint32(0), resultTx.DeliverTx.Code) assert.Equal(t, uint32(0), resultTx.DeliverTx.Code)
// query sender // query sender
res, body = request(t, port, "GET", "/accounts/"+sendAddr, nil) acc = getAccount(t, sendAddr)
require.Equal(t, http.StatusOK, res.StatusCode, body) coins := acc.GetCoins()
var m auth.BaseAccount
err := json.Unmarshal([]byte(body), &m)
require.Nil(t, err)
coins := m.Coins
mycoins := coins[0] mycoins := coins[0]
assert.Equal(t, coinDenom, mycoins.Denom) assert.Equal(t, coinDenom, mycoins.Denom)
assert.Equal(t, coinAmount-1, mycoins.Amount) assert.Equal(t, initialBalance[0].Amount-1, mycoins.Amount)
// query receiver // query receiver
res, body = request(t, port, "GET", "/accounts/"+receiveAddr, nil) acc = getAccount(t, receiveAddr)
require.Equal(t, http.StatusOK, res.StatusCode, body) coins = acc.GetCoins()
err = json.Unmarshal([]byte(body), &m)
require.Nil(t, err)
coins = m.Coins
mycoins = coins[0] mycoins = coins[0]
assert.Equal(t, coinDenom, mycoins.Denom) assert.Equal(t, coinDenom, mycoins.Denom)
assert.Equal(t, int64(1), mycoins.Amount) assert.Equal(t, int64(1), mycoins.Amount)
@ -254,6 +247,9 @@ func TestCoinSend(t *testing.T) {
func TestIBCTransfer(t *testing.T) { func TestIBCTransfer(t *testing.T) {
acc := getAccount(t, sendAddr)
initialBalance := acc.GetCoins()
// create TX // create TX
resultTx := doIBCTransfer(t, port, seed) resultTx := doIBCTransfer(t, port, seed)
@ -264,16 +260,11 @@ func TestIBCTransfer(t *testing.T) {
assert.Equal(t, uint32(0), resultTx.DeliverTx.Code) assert.Equal(t, uint32(0), resultTx.DeliverTx.Code)
// query sender // query sender
res, body := request(t, port, "GET", "/accounts/"+sendAddr, nil) acc = getAccount(t, sendAddr)
require.Equal(t, http.StatusOK, res.StatusCode, body) coins := acc.GetCoins()
var m auth.BaseAccount
err := json.Unmarshal([]byte(body), &m)
require.Nil(t, err)
coins := m.Coins
mycoins := coins[0] mycoins := coins[0]
assert.Equal(t, coinDenom, mycoins.Denom) assert.Equal(t, coinDenom, mycoins.Denom)
assert.Equal(t, coinAmount-2, mycoins.Amount) assert.Equal(t, initialBalance[0].Amount-1, mycoins.Amount)
// TODO: query ibc egress packet state // TODO: query ibc egress packet state
} }
@ -339,16 +330,12 @@ func startTMAndLCD() (*nm.Node, net.Listener, error) {
config.Consensus.SkipTimeoutCommit = false config.Consensus.SkipTimeoutCommit = false
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
logger = log.NewFilter(logger, log.AllowError()) // logger = log.NewFilter(logger, log.AllowError())
privValidatorFile := config.PrivValidatorFile() privValidatorFile := config.PrivValidatorFile()
privVal := tmtypes.LoadOrGenPrivValidatorFS(privValidatorFile) privVal := pvm.LoadOrGenFilePV(privValidatorFile)
dbs := map[string]dbm.DB{ db := dbm.NewMemDB()
"main": dbm.NewMemDB(), app := bapp.NewBasecoinApp(logger, db)
"acc": dbm.NewMemDB(), cdc = bapp.MakeCodec() // XXX
"ibc": dbm.NewMemDB(),
"staking": dbm.NewMemDB(),
}
app := bapp.NewBasecoinApp(logger, dbs)
genesisFile := config.GenesisFile() genesisFile := config.GenesisFile()
genDoc, err := tmtypes.GenesisDocFromFile(genesisFile) genDoc, err := tmtypes.GenesisDocFromFile(genesisFile)
@ -372,8 +359,6 @@ func startTMAndLCD() (*nm.Node, net.Listener, error) {
} }
genDoc.AppStateJSON = stateBytes genDoc.AppStateJSON = stateBytes
cdc := wire.NewCodec()
// LCD listen address // LCD listen address
port = fmt.Sprintf("%d", 17377) // XXX port = fmt.Sprintf("%d", 17377) // XXX
listenAddr := fmt.Sprintf("tcp://localhost:%s", port) // XXX listenAddr := fmt.Sprintf("tcp://localhost:%s", port) // XXX
@ -386,7 +371,7 @@ func startTMAndLCD() (*nm.Node, net.Listener, error) {
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
lcd, err := startLCD(cdc, logger, listenAddr) lcd, err := startLCD(logger, listenAddr)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -425,7 +410,7 @@ func startTM(cfg *tmcfg.Config, logger log.Logger, genDoc *tmtypes.GenesisDoc, p
} }
// start the LCD. note this blocks! // start the LCD. note this blocks!
func startLCD(cdc *wire.Codec, logger log.Logger, listenAddr string) (net.Listener, error) { func startLCD(logger log.Logger, listenAddr string) (net.Listener, error) {
handler := createHandler(cdc) handler := createHandler(cdc)
return tmrpc.StartHTTPServer(listenAddr, handler, logger) return tmrpc.StartHTTPServer(listenAddr, handler, logger)
} }
@ -447,6 +432,16 @@ func request(t *testing.T, port, method, path string, payload []byte) (*http.Res
return res, string(output) return res, string(output)
} }
func getAccount(t *testing.T, sendAddr string) sdk.Account {
// get the account to get the sequence
res, body := request(t, port, "GET", "/accounts/"+sendAddr, nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var acc sdk.Account
err := cdc.UnmarshalJSON([]byte(body), &acc)
require.Nil(t, err)
return acc
}
func doSend(t *testing.T, port, seed string) (receiveAddr string, resultTx ctypes.ResultBroadcastTxCommit) { func doSend(t *testing.T, port, seed string) (receiveAddr string, resultTx ctypes.ResultBroadcastTxCommit) {
// create receive address // create receive address
@ -455,20 +450,15 @@ func doSend(t *testing.T, port, seed string) (receiveAddr string, resultTx ctype
require.Nil(t, err) require.Nil(t, err)
receiveAddr = receiveInfo.PubKey.Address().String() receiveAddr = receiveInfo.PubKey.Address().String()
// get the account to get the sequence acc := getAccount(t, sendAddr)
res, body := request(t, port, "GET", "/accounts/"+sendAddr, nil) sequence := acc.GetSequence()
// require.Equal(t, http.StatusOK, res.StatusCode, body)
acc := auth.BaseAccount{}
err = json.Unmarshal([]byte(body), &acc)
require.Nil(t, err)
sequence := acc.Sequence
// send // send
jsonStr := []byte(fmt.Sprintf(`{ "name":"%s", "password":"%s", "sequence":%d, "amount":[{ "denom": "%s", "amount": 1 }] }`, name, password, sequence, coinDenom)) jsonStr := []byte(fmt.Sprintf(`{ "name":"%s", "password":"%s", "sequence":%d, "amount":[{ "denom": "%s", "amount": 1 }] }`, name, password, sequence, coinDenom))
res, body = request(t, port, "POST", "/accounts/"+receiveAddr+"/send", jsonStr) res, body := request(t, port, "POST", "/accounts/"+receiveAddr+"/send", jsonStr)
require.Equal(t, http.StatusOK, res.StatusCode, body) require.Equal(t, http.StatusOK, res.StatusCode, body)
err = json.Unmarshal([]byte(body), &resultTx) err = cdc.UnmarshalJSON([]byte(body), &resultTx)
require.Nil(t, err) require.Nil(t, err)
return receiveAddr, resultTx return receiveAddr, resultTx
@ -483,19 +473,15 @@ func doIBCTransfer(t *testing.T, port, seed string) (resultTx ctypes.ResultBroad
receiveAddr := receiveInfo.PubKey.Address().String() receiveAddr := receiveInfo.PubKey.Address().String()
// get the account to get the sequence // get the account to get the sequence
res, body := request(t, port, "GET", "/accounts/"+sendAddr, nil) acc := getAccount(t, sendAddr)
// require.Equal(t, http.StatusOK, res.StatusCode, body) sequence := acc.GetSequence()
acc := auth.BaseAccount{}
err = json.Unmarshal([]byte(body), &acc)
require.Nil(t, err)
sequence := acc.Sequence
// send // send
jsonStr := []byte(fmt.Sprintf(`{ "name":"%s", "password":"%s", "sequence":%d, "amount":[{ "denom": "%s", "amount": 1 }] }`, name, password, sequence, coinDenom)) jsonStr := []byte(fmt.Sprintf(`{ "name":"%s", "password":"%s", "sequence":%d, "amount":[{ "denom": "%s", "amount": 1 }] }`, name, password, sequence, coinDenom))
res, body = request(t, port, "POST", "/ibc/testchain/"+receiveAddr+"/send", jsonStr) res, body := request(t, port, "POST", "/ibc/testchain/"+receiveAddr+"/send", jsonStr)
require.Equal(t, http.StatusOK, res.StatusCode, body) require.Equal(t, http.StatusOK, res.StatusCode, body)
err = json.Unmarshal([]byte(body), &resultTx) err = cdc.UnmarshalJSON([]byte(body), &resultTx)
require.Nil(t, err) require.Nil(t, err)
return resultTx return resultTx
@ -517,7 +503,7 @@ func waitForHeight(height int64) {
} }
res.Body.Close() res.Body.Close()
err = json.Unmarshal([]byte(body), &resultBlock) err = cdc.UnmarshalJSON([]byte(body), &resultBlock)
if err != nil { if err != nil {
fmt.Println("RES", res) fmt.Println("RES", res)
fmt.Println("BODY", string(body)) fmt.Println("BODY", string(body))
@ -537,8 +523,6 @@ func waitForStart() {
for { for {
time.Sleep(time.Second) time.Sleep(time.Second)
var resultBlock ctypes.ResultBlock
url := fmt.Sprintf("http://localhost:%v%v", port, "/blocks/latest") url := fmt.Sprintf("http://localhost:%v%v", port, "/blocks/latest")
res, err := http.Get(url) res, err := http.Get(url)
if err != nil { if err != nil {
@ -557,7 +541,8 @@ func waitForStart() {
} }
res.Body.Close() res.Body.Close()
err = json.Unmarshal([]byte(body), &resultBlock) resultBlock := new(ctypes.ResultBlock)
err = cdc.UnmarshalJSON([]byte(body), &resultBlock)
if err != nil { if err != nil {
fmt.Println("RES", res) fmt.Println("RES", res)
fmt.Println("BODY", string(body)) fmt.Println("BODY", string(body))

12
client/lcd/wire.go Normal file
View File

@ -0,0 +1,12 @@
package lcd
import (
amino "github.com/tendermint/go-amino"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
)
var cdc = amino.NewCodec()
func init() {
ctypes.RegisterAmino(cdc)
}

View File

@ -1,7 +1,6 @@
package rpc package rpc
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"strconv" "strconv"
@ -49,7 +48,7 @@ func getBlock(height *int64) ([]byte, error) {
// TODO move maarshalling into cmd/rest functions // TODO move maarshalling into cmd/rest functions
// output, err := tmwire.MarshalJSON(res) // output, err := tmwire.MarshalJSON(res)
output, err := json.MarshalIndent(res, "", " ") output, err := cdc.MarshalJSON(res)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -65,7 +64,7 @@ func GetChainHeight() (int64, error) {
if err != nil { if err != nil {
return -1, err return -1, err
} }
height := status.LatestBlockHeight height := status.SyncInfo.LatestBlockHeight
return height, nil return height, nil
} }

View File

@ -1,13 +1,11 @@
package rpc package rpc
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"strconv" "strconv"
"github.com/spf13/cobra" "github.com/spf13/cobra"
wire "github.com/tendermint/go-wire"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/context"
@ -41,8 +39,8 @@ func printNodeStatus(cmd *cobra.Command, args []string) error {
return err return err
} }
output, err := wire.MarshalJSON(status) output, err := cdc.MarshalJSON(status)
// output, err := json.MarshalIndent(res, " ", "") // output, err := cdc.MarshalJSONIndent(res, " ", "")
if err != nil { if err != nil {
return err return err
} }
@ -62,7 +60,7 @@ func NodeInfoRequestHandler(w http.ResponseWriter, r *http.Request) {
} }
nodeInfo := status.NodeInfo nodeInfo := status.NodeInfo
output, err := json.MarshalIndent(nodeInfo, "", " ") output, err := cdc.MarshalJSON(nodeInfo)
if err != nil { if err != nil {
w.WriteHeader(500) w.WriteHeader(500)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
@ -79,7 +77,7 @@ func NodeSyncingRequestHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
syncing := status.Syncing syncing := status.SyncInfo.Syncing
if err != nil { if err != nil {
w.WriteHeader(500) w.WriteHeader(500)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))

View File

@ -1,7 +1,6 @@
package rpc package rpc
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"strconv" "strconv"
@ -37,7 +36,7 @@ func GetValidators(height *int64) ([]byte, error) {
return nil, err return nil, err
} }
output, err := json.MarshalIndent(res, "", " ") output, err := cdc.MarshalJSON(res)
if err != nil { if err != nil {
return nil, err return nil, err
} }

12
client/rpc/wire.go Normal file
View File

@ -0,0 +1,12 @@
package rpc
import (
amino "github.com/tendermint/go-amino"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
)
var cdc = amino.NewCodec()
func init() {
ctypes.RegisterAmino(cdc)
}

View File

@ -28,29 +28,11 @@ var (
// TODO: distinguish from basecoin // TODO: distinguish from basecoin
func generateApp(rootDir string, logger log.Logger) (abci.Application, error) { func generateApp(rootDir string, logger log.Logger) (abci.Application, error) {
dataDir := filepath.Join(rootDir, "data") dataDir := filepath.Join(rootDir, "data")
dbMain, err := dbm.NewGoLevelDB("gaia", dataDir) db, err := dbm.NewGoLevelDB("gaia", dataDir)
if err != nil { if err != nil {
return nil, err return nil, err
} }
dbAcc, err := dbm.NewGoLevelDB("gaia-acc", dataDir) bapp := app.NewBasecoinApp(logger, db)
if err != nil {
return nil, err
}
dbIBC, err := dbm.NewGoLevelDB("gaia-ibc", dataDir)
if err != nil {
return nil, err
}
dbStaking, err := dbm.NewGoLevelDB("gaia-staking", dataDir)
if err != nil {
return nil, err
}
dbs := map[string]dbm.DB{
"main": dbMain,
"acc": dbAcc,
"ibc": dbIBC,
"staking": dbStaking,
}
bapp := app.NewBasecoinApp(logger, dbs)
return bapp, nil return bapp, nil
} }

View File

@ -40,7 +40,7 @@ Basecoin implements a `BaseApp` state machine using the `x/auth` and `x/bank` ex
which define how transaction signers are authenticated and how coins are transferred. which define how transaction signers are authenticated and how coins are transferred.
It should also use `x/ibc` and probably a simple staking extension. It should also use `x/ibc` and probably a simple staking extension.
Basecoin and the native `x` extensions use go-wire for all serialization needs, Basecoin and the native `x` extensions use go-amino for all serialization needs,
including for transactions and accounts. including for transactions and accounts.
## Your Cosmos App ## Your Cosmos App
@ -62,7 +62,7 @@ Ethermint is a new implementation of `BaseApp` that does not depend on Basecoin.
Instead of `cosmos-sdk/x/` it has its own `ethermint/x` based on `go-ethereum`. Instead of `cosmos-sdk/x/` it has its own `ethermint/x` based on `go-ethereum`.
Ethermint uses a Patricia store for its accounts, and an IAVL store for IBC. Ethermint uses a Patricia store for its accounts, and an IAVL store for IBC.
It has `x/ante`, which is quite similar to Basecoin's but uses RLP instead of go-wire. It has `x/ante`, which is quite similar to Basecoin's but uses RLP instead of go-amino.
Instead of `x/bank`, it has `x/eth`, which defines the single Ethereum transaction type Instead of `x/bank`, it has `x/eth`, which defines the single Ethereum transaction type
and all the semantics of the Ethereum state machine. and all the semantics of the Ethereum state machine.

View File

@ -22,7 +22,7 @@ The SDK distinguishes between transactions (Tx) and messages
Users can create messages containing arbitrary information by Users can create messages containing arbitrary information by
implementing the `Msg` interface: implementing the `Msg` interface:
```golang ```go
type Msg interface { type Msg interface {
// Return the message type. // Return the message type.
@ -68,7 +68,7 @@ but this is mostly for convenience and not type-safe.
For instance, the `Basecoin` message types are defined in `x/bank/tx.go`: For instance, the `Basecoin` message types are defined in `x/bank/tx.go`:
```golang ```go
type SendMsg struct { type SendMsg struct {
Inputs []Input `json:"inputs"` Inputs []Input `json:"inputs"`
Outputs []Output `json:"outputs"` Outputs []Output `json:"outputs"`
@ -82,7 +82,7 @@ type IssueMsg struct {
Each specifies the addresses that must sign the message: Each specifies the addresses that must sign the message:
```golang ```go
func (msg SendMsg) GetSigners() []sdk.Address { func (msg SendMsg) GetSigners() []sdk.Address {
addrs := make([]sdk.Address, len(msg.Inputs)) addrs := make([]sdk.Address, len(msg.Inputs))
for i, in := range msg.Inputs { for i, in := range msg.Inputs {
@ -100,7 +100,7 @@ func (msg IssueMsg) GetSigners() []sdk.Address {
A transaction is a message with additional information for authentication: A transaction is a message with additional information for authentication:
```golang ```go
type Tx interface { type Tx interface {
GetMsg() Msg GetMsg() Msg
@ -120,7 +120,7 @@ The `tx.GetSignatures()` method returns a list of signatures, which must match
the list of addresses returned by `tx.Msg.GetSigners()`. The signatures come in the list of addresses returned by `tx.Msg.GetSigners()`. The signatures come in
a standard form: a standard form:
```golang ```go
type StdSignature struct { type StdSignature struct {
crypto.PubKey // optional crypto.PubKey // optional
crypto.Signature crypto.Signature
@ -146,7 +146,7 @@ to return this.
The standard way to create a transaction from a message is to use the `StdTx`: The standard way to create a transaction from a message is to use the `StdTx`:
```golang ```go
type StdTx struct { type StdTx struct {
Msg Msg
Signatures []StdSignature Signatures []StdSignature
@ -164,12 +164,12 @@ When initializing an application, a developer must specify a `TxDecoder`
function which determines how an arbitrary byte array should be unmarshalled function which determines how an arbitrary byte array should be unmarshalled
into a `Tx`: into a `Tx`:
```golang ```go
type TxDecoder func(txBytes []byte) (Tx, error) type TxDecoder func(txBytes []byte) (Tx, error)
``` ```
In `Basecoin`, we use the Tendermint wire format and the `go-wire` library for In `Basecoin`, we use the Tendermint wire format and the `go-amino` library for
encoding and decoding all message types. The `go-wire` library has the nice encoding and decoding all message types. The `go-amino` library has the nice
property that it can unmarshal into interface types, but it requires the property that it can unmarshal into interface types, but it requires the
relevant types to be registered ahead of type. Registration happens on a relevant types to be registered ahead of type. Registration happens on a
`Codec` object, so as not to taint the global name space. `Codec` object, so as not to taint the global name space.
@ -177,7 +177,7 @@ relevant types to be registered ahead of type. Registration happens on a
For instance, in `Basecoin`, we wish to register the `SendMsg` and `IssueMsg` For instance, in `Basecoin`, we wish to register the `SendMsg` and `IssueMsg`
types: types:
```golang ```go
cdc.RegisterInterface((*sdk.Msg)(nil), nil) cdc.RegisterInterface((*sdk.Msg)(nil), nil)
cdc.RegisterConcrete(bank.SendMsg{}, "cosmos-sdk/SendMsg", nil) cdc.RegisterConcrete(bank.SendMsg{}, "cosmos-sdk/SendMsg", nil)
cdc.RegisterConcrete(bank.IssueMsg{}, "cosmos-sdk/IssueMsg", nil) cdc.RegisterConcrete(bank.IssueMsg{}, "cosmos-sdk/IssueMsg", nil)
@ -186,24 +186,61 @@ cdc.RegisterConcrete(bank.IssueMsg{}, "cosmos-sdk/IssueMsg", nil)
Note how each concrete type is given a name - these name determine the type's Note how each concrete type is given a name - these name determine the type's
unique "prefix bytes" during encoding. A registered type will always use the unique "prefix bytes" during encoding. A registered type will always use the
same prefix-bytes, regardless of what interface it is satisfying. For more same prefix-bytes, regardless of what interface it is satisfying. For more
details, see the [go-wire documentation](https://github.com/tendermint/go-wire/blob/develop). details, see the [go-amino documentation](https://github.com/tendermint/go-amino/blob/develop).
## MultiStore ## Storage
### MultiStore is like a filesystem ### MultiStore
### Mounting an IAVLStore
MultiStore is like a root filesystem of an operating system, except
all the entries are fully Merkleized. You mount onto a MultiStore
any number of Stores. Currently only KVStores are supported, but in
the future we may support more kinds of stores, such as a HeapStore
or a NDStore for multidimensional storage.
The MultiStore as well as all mounted stores provide caching (aka
cache-wrapping) for intermediate state (aka software transactional
memory) during the execution of transactions. In the case of the
KVStore, this also works for iterators. For example, after running
the app's AnteHandler, the MultiStore is cache-wrapped (and each
store is also cache-wrapped) so that should processing of the
transaction fail, at least the transaction fees are paid and
sequence incremented.
The MultiStore as well as all stores support (or will support)
historical state pruning and snapshotting and various kinds of
queries with proofs.
### KVStore
Here we'll focus on the IAVLStore, which is a kind of KVStore.
IAVLStore is a fast balanced dynamic Merkle store that also supports
iteration, and of course cache-wrapping, state pruning, and various
queries with proofs, such as proofs of existence, absence, range,
and so on.
Here's how you mount them to a MultiStore.
```go
mainDB, catDB := dbm.NewMemDB(), dbm.NewMemDB()
fooKey := sdk.NewKVStoreKey("foo")
barKey := sdk.NewKVStoreKey("bar")
catKey := sdk.NewKVStoreKey("cat")
ms := NewCommitMultiStore(mainDB)
ms.MountStoreWithDB(fooKey, sdk.StoreTypeIAVL, nil)
ms.MountStoreWithDB(barKey, sdk.StoreTypeIAVL, nil)
ms.MountStoreWithDB(catKey, sdk.StoreTypeIAVL, catDB)
``` ```
TODO:
- IAVLStore: Fast balanced dynamic Merkle store. In the example above, all IAVL nodes (inner and leaf) will be stored
- supports iteration. in mainDB with the prefix of "s/k:foo/" and "s/k:bar/" respectively,
- MultiStore: multiple Merkle tree backends in a single store thus sharing the mainDB. All IAVL nodes (inner and leaf) for the
- allows using Ethereum Patricia Trie and Tendermint IAVL in same app cat KVStore are stored separately in catDB with the prefix of
- Provide caching for intermediate state during execution of blocks and transactions (including for iteration) "s/\_/". The "s/k:KEY/" and "s/\_/" prefixes are there to
- Historical state pruning and snapshotting. disambiguate store items from other items of non-storage concern.
- Query proofs (existence, absence, range, etc.) on current and retained historical state.
```
## Context ## Context
@ -223,7 +260,7 @@ Many methods on SDK objects receive a context as the first argument.
Transaction processing in the SDK is defined through `Handler` functions: Transaction processing in the SDK is defined through `Handler` functions:
```golang ```go
type Handler func(ctx Context, tx Tx) Result type Handler func(ctx Context, tx Tx) Result
``` ```
@ -237,7 +274,7 @@ to a particular store (or two or more). Access to stores is managed using
capabilities keys and mappers. When a handler is initialized, it is passed a capabilities keys and mappers. When a handler is initialized, it is passed a
key or mapper that gives it access to the relevant stores. key or mapper that gives it access to the relevant stores.
```golang ```go
// File: cosmos-sdk/examples/basecoin/app/init_stores.go // File: cosmos-sdk/examples/basecoin/app/init_stores.go
app.BaseApp.MountStore(app.capKeyMainStore, sdk.StoreTypeIAVL) app.BaseApp.MountStore(app.capKeyMainStore, sdk.StoreTypeIAVL)
app.accountMapper = auth.NewAccountMapper( app.accountMapper = auth.NewAccountMapper(

View File

@ -18,8 +18,7 @@ store), and it must have a deterministic action. The transaction is the
main piece of one request. main piece of one request.
We currently make heavy use of We currently make heavy use of
`go-wire <https://github.com/tendermint/go-wire>`__ and `go-amino <https://github.com/tendermint/go-amino>`__ to
`data <https://github.com/tendermint/go-wire/tree/master/data>`__ to
provide binary and json encodings and decodings for ``struct`` or provide binary and json encodings and decodings for ``struct`` or
interface\ ``objects. Here, encoding and decoding operations are designed to operate with interfaces nested any amount times (like an onion!). There is one public``\ TxMapper\` interface\ ``objects. Here, encoding and decoding operations are designed to operate with interfaces nested any amount times (like an onion!). There is one public``\ TxMapper\`
in the basecoin root package, and all modules can register their own in the basecoin root package, and all modules can register their own
@ -162,13 +161,13 @@ also implements the ``Handler`` interface. We then register a list of
modules with the dispatcher. Every module has a unique ``Name()``, which modules with the dispatcher. Every module has a unique ``Name()``, which
is used for isolating its state space. We use this same name for routing is used for isolating its state space. We use this same name for routing
transactions. Each transaction implementation must be registed with transactions. Each transaction implementation must be registed with
go-wire via ``TxMapper``, so we just look at the registered name of this go-amino via ``TxMapper``, so we just look at the registered name of this
transaction, which should be of the form ``<module name>/xxx``. The transaction, which should be of the form ``<module name>/xxx``. The
dispatcher grabs the appropriate module name from the tx name and routes dispatcher grabs the appropriate module name from the tx name and routes
it if the module is present. it if the module is present.
This all seems like a bit of magic, but really we're just making use of This all seems like a bit of magic, but really we're just making use of
go-wire magic that we are already using, rather than add another layer. go-amino magic that we are already using, rather than add another layer.
For all the transactions to be properly routed, the only thing you need For all the transactions to be properly routed, the only thing you need
to remember is to use the following pattern: to remember is to use the following pattern:

View File

@ -278,8 +278,8 @@ into a ``Tx``:
type TxDecoder func(txBytes []byte) (Tx, error) type TxDecoder func(txBytes []byte) (Tx, error)
In ``Basecoin``, we use the Tendermint wire format and the ``go-wire`` library for In ``Basecoin``, we use the Tendermint wire format and the ``go-amino`` library for
encoding and decoding all message types. The ``go-wire`` library has the nice encoding and decoding all message types. The ``go-amino`` library has the nice
property that it can unmarshal into interface types, but it requires the property that it can unmarshal into interface types, but it requires the
relevant types to be registered ahead of type. Registration happens on a relevant types to be registered ahead of type. Registration happens on a
``Codec`` object, so as not to taint the global name space. ``Codec`` object, so as not to taint the global name space.
@ -296,7 +296,7 @@ types:
Note how each concrete type is given a name - these name determine the type's Note how each concrete type is given a name - these name determine the type's
unique "prefix bytes" during encoding. A registered type will always use the unique "prefix bytes" during encoding. A registered type will always use the
same prefix-bytes, regardless of what interface it is satisfying. For more same prefix-bytes, regardless of what interface it is satisfying. For more
details, see the `go-wire documentation <https://github.com/tendermint/go-wire/tree/develop>`__. details, see the `go-amino documentation <https://github.com/tendermint/go-amino/tree/develop>`__.
MultiStore MultiStore

View File

@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
abci "github.com/tendermint/abci/types" abci "github.com/tendermint/abci/types"
oldwire "github.com/tendermint/go-wire"
cmn "github.com/tendermint/tmlibs/common" cmn "github.com/tendermint/tmlibs/common"
dbm "github.com/tendermint/tmlibs/db" dbm "github.com/tendermint/tmlibs/db"
"github.com/tendermint/tmlibs/log" "github.com/tendermint/tmlibs/log"
@ -37,26 +36,34 @@ type BasecoinApp struct {
// Manage getting and setting accounts // Manage getting and setting accounts
accountMapper sdk.AccountMapper accountMapper sdk.AccountMapper
// Handle fees
feeHandler sdk.FeeHandler
} }
func NewBasecoinApp(logger log.Logger, dbs map[string]dbm.DB) *BasecoinApp { func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp {
// create your application object
// Create app-level codec for txs and accounts.
var cdc = MakeCodec()
// Create your application object.
var app = &BasecoinApp{ var app = &BasecoinApp{
BaseApp: bam.NewBaseApp(appName, logger, dbs["main"]), BaseApp: bam.NewBaseApp(appName, logger, db),
cdc: MakeCodec(), cdc: cdc,
capKeyMainStore: sdk.NewKVStoreKey("main"), capKeyMainStore: sdk.NewKVStoreKey("main"),
capKeyAccountStore: sdk.NewKVStoreKey("acc"), capKeyAccountStore: sdk.NewKVStoreKey("acc"),
capKeyIBCStore: sdk.NewKVStoreKey("ibc"), capKeyIBCStore: sdk.NewKVStoreKey("ibc"),
capKeyStakingStore: sdk.NewKVStoreKey("stake"), capKeyStakingStore: sdk.NewKVStoreKey("stake"),
} }
// define the accountMapper // Define the accountMapper.
app.accountMapper = auth.NewAccountMapperSealed( app.accountMapper = auth.NewAccountMapper(
cdc,
app.capKeyMainStore, // target store app.capKeyMainStore, // target store
&types.AppAccount{}, // prototype &types.AppAccount{}, // prototype
) ).Seal()
// add handlers // Add handlers.
coinKeeper := bank.NewCoinKeeper(app.accountMapper) coinKeeper := bank.NewCoinKeeper(app.accountMapper)
ibcMapper := ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore) ibcMapper := ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore)
stakeKeeper := simplestake.NewKeeper(app.capKeyStakingStore, coinKeeper) stakeKeeper := simplestake.NewKeeper(app.capKeyStakingStore, coinKeeper)
@ -65,16 +72,14 @@ func NewBasecoinApp(logger log.Logger, dbs map[string]dbm.DB) *BasecoinApp {
AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)). AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)).
AddRoute("simplestake", simplestake.NewHandler(stakeKeeper)) AddRoute("simplestake", simplestake.NewHandler(stakeKeeper))
// initialize BaseApp // Define the feeHandler.
app.feeHandler = auth.BurnFeeHandler
// Initialize BaseApp.
app.SetTxDecoder(app.txDecoder) app.SetTxDecoder(app.txDecoder)
app.SetInitChainer(app.initChainer) app.SetInitChainer(app.initChainer)
app.MountStoreWithDB(app.capKeyMainStore, sdk.StoreTypeIAVL, dbs["main"]) app.MountStoresIAVL(app.capKeyMainStore, app.capKeyAccountStore, app.capKeyIBCStore, app.capKeyStakingStore)
app.MountStoreWithDB(app.capKeyAccountStore, sdk.StoreTypeIAVL, dbs["acc"]) app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeHandler))
app.MountStoreWithDB(app.capKeyIBCStore, sdk.StoreTypeIAVL, dbs["ibc"])
app.MountStoreWithDB(app.capKeyStakingStore, sdk.StoreTypeIAVL, dbs["staking"])
// NOTE: Broken until #532 lands
//app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore, app.capKeyStakingStore)
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper))
err := app.LoadLatestVersion(app.capKeyMainStore) err := app.LoadLatestVersion(app.capKeyMainStore)
if err != nil { if err != nil {
cmn.Exit(err.Error()) cmn.Exit(err.Error())
@ -83,42 +88,30 @@ func NewBasecoinApp(logger log.Logger, dbs map[string]dbm.DB) *BasecoinApp {
return app return app
} }
// custom tx codec // Custom tx codec
// TODO: use new go-wire
func MakeCodec() *wire.Codec { func MakeCodec() *wire.Codec {
const msgTypeSend = 0x1 var cdc = wire.NewCodec()
const msgTypeIssue = 0x2
const msgTypeQuiz = 0x3
const msgTypeSetTrend = 0x4
const msgTypeIBCTransferMsg = 0x5
const msgTypeIBCReceiveMsg = 0x6
const msgTypeBondMsg = 0x7
const msgTypeUnbondMsg = 0x8
var _ = oldwire.RegisterInterface(
struct{ sdk.Msg }{},
oldwire.ConcreteType{bank.SendMsg{}, msgTypeSend},
oldwire.ConcreteType{bank.IssueMsg{}, msgTypeIssue},
oldwire.ConcreteType{ibc.IBCTransferMsg{}, msgTypeIBCTransferMsg},
oldwire.ConcreteType{ibc.IBCReceiveMsg{}, msgTypeIBCReceiveMsg},
oldwire.ConcreteType{simplestake.BondMsg{}, msgTypeBondMsg},
oldwire.ConcreteType{simplestake.UnbondMsg{}, msgTypeUnbondMsg},
)
const accTypeApp = 0x1 // Register Msgs
var _ = oldwire.RegisterInterface( cdc.RegisterInterface((*sdk.Msg)(nil), nil)
struct{ sdk.Account }{}, cdc.RegisterConcrete(bank.SendMsg{}, "basecoin/Send", nil)
oldwire.ConcreteType{&types.AppAccount{}, accTypeApp}, cdc.RegisterConcrete(bank.IssueMsg{}, "basecoin/Issue", nil)
) cdc.RegisterConcrete(ibc.IBCTransferMsg{}, "basecoin/IBCTransferMsg", nil)
cdc := wire.NewCodec() cdc.RegisterConcrete(ibc.IBCReceiveMsg{}, "basecoin/IBCReceiveMsg", nil)
cdc.RegisterConcrete(simplestake.BondMsg{}, "basecoin/BondMsg", nil)
cdc.RegisterConcrete(simplestake.UnbondMsg{}, "basecoin/UnbondMsg", nil)
// Register AppAccount
cdc.RegisterInterface((*sdk.Account)(nil), nil)
cdc.RegisterConcrete(&types.AppAccount{}, "basecoin/Account", nil)
// Register crypto.
wire.RegisterCrypto(cdc)
// cdc.RegisterInterface((*sdk.Msg)(nil), nil)
// bank.RegisterWire(cdc) // Register bank.[SendMsg,IssueMsg] types.
// crypto.RegisterWire(cdc) // Register crypto.[PubKey,PrivKey,Signature] types.
// ibc.RegisterWire(cdc) // Register ibc.[IBCTransferMsg, IBCReceiveMsg] types.
return cdc return cdc
} }
// custom logic for transaction decoding // Custom logic for transaction decoding
func (app *BasecoinApp) txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) { func (app *BasecoinApp) txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) {
var tx = sdk.StdTx{} var tx = sdk.StdTx{}
@ -127,7 +120,7 @@ func (app *BasecoinApp) txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) {
} }
// StdTx.Msg is an interface. The concrete types // StdTx.Msg is an interface. The concrete types
// are registered by MakeTxCodec in bank.RegisterWire. // are registered by MakeTxCodec in bank.RegisterAmino.
err := app.cdc.UnmarshalBinary(txBytes, &tx) err := app.cdc.UnmarshalBinary(txBytes, &tx)
if err != nil { if err != nil {
return nil, sdk.ErrTxDecode("").TraceCause(err, "") return nil, sdk.ErrTxDecode("").TraceCause(err, "")
@ -135,7 +128,7 @@ func (app *BasecoinApp) txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) {
return tx, nil return tx, nil
} }
// custom logic for basecoin initialization // Custom logic for basecoin initialization
func (app *BasecoinApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { func (app *BasecoinApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
stateJSON := req.AppStateBytes stateJSON := req.AppStateBytes

View File

@ -85,20 +85,15 @@ var (
} }
) )
func loggerAndDBs() (log.Logger, map[string]dbm.DB) { func loggerAndDB() (log.Logger, dbm.DB) {
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app")
dbs := map[string]dbm.DB{ db := dbm.NewMemDB()
"main": dbm.NewMemDB(), return logger, db
"acc": dbm.NewMemDB(),
"ibc": dbm.NewMemDB(),
"staking": dbm.NewMemDB(),
}
return logger, dbs
} }
func newBasecoinApp() *BasecoinApp { func newBasecoinApp() *BasecoinApp {
logger, dbs := loggerAndDBs() logger, db := loggerAndDB()
return NewBasecoinApp(logger, dbs) return NewBasecoinApp(logger, db)
} }
func setGenesisAccounts(bapp *BasecoinApp, accs ...auth.BaseAccount) error { func setGenesisAccounts(bapp *BasecoinApp, accs ...auth.BaseAccount) error {
@ -142,8 +137,8 @@ func TestMsgs(t *testing.T) {
} }
func TestSortGenesis(t *testing.T) { func TestSortGenesis(t *testing.T) {
logger, dbs := loggerAndDBs() logger, db := loggerAndDB()
bapp := NewBasecoinApp(logger, dbs) bapp := NewBasecoinApp(logger, db)
// Note the order: the coins are unsorted! // Note the order: the coins are unsorted!
coinDenom1, coinDenom2 := "foocoin", "barcoin" coinDenom1, coinDenom2 := "foocoin", "barcoin"
@ -184,8 +179,8 @@ func TestSortGenesis(t *testing.T) {
} }
func TestGenesis(t *testing.T) { func TestGenesis(t *testing.T) {
logger, dbs := loggerAndDBs() logger, db := loggerAndDB()
bapp := NewBasecoinApp(logger, dbs) bapp := NewBasecoinApp(logger, db)
// Construct some genesis bytes to reflect basecoin/types/AppAccount // Construct some genesis bytes to reflect basecoin/types/AppAccount
pk := crypto.GenPrivKeyEd25519().PubKey() pk := crypto.GenPrivKeyEd25519().PubKey()
@ -207,7 +202,7 @@ func TestGenesis(t *testing.T) {
assert.Equal(t, acc, res1) assert.Equal(t, acc, res1)
// reload app and ensure the account is still there // reload app and ensure the account is still there
bapp = NewBasecoinApp(logger, dbs) bapp = NewBasecoinApp(logger, db)
ctx = bapp.BaseApp.NewContext(true, abci.Header{}) ctx = bapp.BaseApp.NewContext(true, abci.Header{})
res1 = bapp.accountMapper.GetAccount(ctx, baseAcc.Address) res1 = bapp.accountMapper.GetAccount(ctx, baseAcc.Address)
assert.Equal(t, acc, res1) assert.Equal(t, acc, res1)
@ -349,10 +344,9 @@ func TestQuizMsg(t *testing.T) {
// Construct genesis state // Construct genesis state
// Construct some genesis bytes to reflect basecoin/types/AppAccount // Construct some genesis bytes to reflect basecoin/types/AppAccount
coins := sdk.Coins{}
baseAcc := auth.BaseAccount{ baseAcc := auth.BaseAccount{
Address: addr1, Address: addr1,
Coins: coins, Coins: nil,
} }
acc1 := &types.AppAccount{baseAcc, "foobart"} acc1 := &types.AppAccount{baseAcc, "foobart"}

View File

@ -27,29 +27,11 @@ var (
func generateApp(rootDir string, logger log.Logger) (abci.Application, error) { func generateApp(rootDir string, logger log.Logger) (abci.Application, error) {
dataDir := filepath.Join(rootDir, "data") dataDir := filepath.Join(rootDir, "data")
dbMain, err := dbm.NewGoLevelDB("basecoin", dataDir) db, err := dbm.NewGoLevelDB("basecoin", dataDir)
if err != nil { if err != nil {
return nil, err return nil, err
} }
dbAcc, err := dbm.NewGoLevelDB("basecoin-acc", dataDir) bapp := app.NewBasecoinApp(logger, db)
if err != nil {
return nil, err
}
dbIBC, err := dbm.NewGoLevelDB("basecoin-ibc", dataDir)
if err != nil {
return nil, err
}
dbStaking, err := dbm.NewGoLevelDB("basecoin-staking", dataDir)
if err != nil {
return nil, err
}
dbs := map[string]dbm.DB{
"main": dbMain,
"acc": dbAcc,
"ibc": dbIBC,
"staking": dbStaking,
}
bapp := app.NewBasecoinApp(logger, dbs)
return bapp, nil return bapp, nil
} }

View File

@ -12,7 +12,7 @@ var _ sdk.Account = (*AppAccount)(nil)
// extending auth.BaseAccount with custom fields. // extending auth.BaseAccount with custom fields.
// //
// This is compatible with the stock auth.AccountStore, since // This is compatible with the stock auth.AccountStore, since
// auth.AccountStore uses the flexible go-wire library. // auth.AccountStore uses the flexible go-amino library.
type AppAccount struct { type AppAccount struct {
auth.BaseAccount auth.BaseAccount
Name string `json:"name"` Name string `json:"name"`
@ -29,7 +29,7 @@ func GetAccountDecoder(cdc *wire.Codec) sdk.AccountDecoder {
return nil, sdk.ErrTxDecode("accBytes are empty") return nil, sdk.ErrTxDecode("accBytes are empty")
} }
acct := new(AppAccount) acct := new(AppAccount)
err = cdc.UnmarshalBinary(accBytes, &acct) err = cdc.UnmarshalBinaryBare(accBytes, &acct)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
abci "github.com/tendermint/abci/types" abci "github.com/tendermint/abci/types"
oldwire "github.com/tendermint/go-wire"
cmn "github.com/tendermint/tmlibs/common" cmn "github.com/tendermint/tmlibs/common"
dbm "github.com/tendermint/tmlibs/db" dbm "github.com/tendermint/tmlibs/db"
"github.com/tendermint/tmlibs/log" "github.com/tendermint/tmlibs/log"
@ -41,13 +40,20 @@ type DemocoinApp struct {
// Manage getting and setting accounts // Manage getting and setting accounts
accountMapper sdk.AccountMapper accountMapper sdk.AccountMapper
// Handle fees
feeHandler sdk.FeeHandler
} }
func NewDemocoinApp(logger log.Logger, dbs map[string]dbm.DB) *DemocoinApp { func NewDemocoinApp(logger log.Logger, db dbm.DB) *DemocoinApp {
// create your application object
// Create app-level codec for txs and accounts.
var cdc = MakeCodec()
// Create your application object.
var app = &DemocoinApp{ var app = &DemocoinApp{
BaseApp: bam.NewBaseApp(appName, logger, dbs["main"]), BaseApp: bam.NewBaseApp(appName, logger, db),
cdc: MakeCodec(), cdc: cdc,
capKeyMainStore: sdk.NewKVStoreKey("main"), capKeyMainStore: sdk.NewKVStoreKey("main"),
capKeyAccountStore: sdk.NewKVStoreKey("acc"), capKeyAccountStore: sdk.NewKVStoreKey("acc"),
capKeyPowStore: sdk.NewKVStoreKey("pow"), capKeyPowStore: sdk.NewKVStoreKey("pow"),
@ -55,13 +61,14 @@ func NewDemocoinApp(logger log.Logger, dbs map[string]dbm.DB) *DemocoinApp {
capKeyStakingStore: sdk.NewKVStoreKey("stake"), capKeyStakingStore: sdk.NewKVStoreKey("stake"),
} }
// define the accountMapper // Define the accountMapper.
app.accountMapper = auth.NewAccountMapperSealed( app.accountMapper = auth.NewAccountMapper(
cdc,
app.capKeyMainStore, // target store app.capKeyMainStore, // target store
&types.AppAccount{}, // prototype &types.AppAccount{}, // prototype
) ).Seal()
// add handlers // Add handlers.
coinKeeper := bank.NewCoinKeeper(app.accountMapper) coinKeeper := bank.NewCoinKeeper(app.accountMapper)
coolKeeper := cool.NewKeeper(app.capKeyMainStore, coinKeeper) coolKeeper := cool.NewKeeper(app.capKeyMainStore, coinKeeper)
powKeeper := pow.NewKeeper(app.capKeyPowStore, pow.NewPowConfig("pow", int64(1)), coinKeeper) powKeeper := pow.NewKeeper(app.capKeyPowStore, pow.NewPowConfig("pow", int64(1)), coinKeeper)
@ -75,17 +82,14 @@ func NewDemocoinApp(logger log.Logger, dbs map[string]dbm.DB) *DemocoinApp {
AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)). AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)).
AddRoute("simplestake", simplestake.NewHandler(stakeKeeper)) AddRoute("simplestake", simplestake.NewHandler(stakeKeeper))
// initialize BaseApp // Define the feeHandler.
app.feeHandler = auth.BurnFeeHandler
// Initialize BaseApp.
app.SetTxDecoder(app.txDecoder) app.SetTxDecoder(app.txDecoder)
app.SetInitChainer(app.initChainerFn(coolKeeper, powKeeper)) app.SetInitChainer(app.initChainerFn(coolKeeper, powKeeper))
app.MountStoreWithDB(app.capKeyMainStore, sdk.StoreTypeIAVL, dbs["main"]) app.MountStoresIAVL(app.capKeyMainStore, app.capKeyAccountStore, app.capKeyPowStore, app.capKeyIBCStore, app.capKeyStakingStore)
app.MountStoreWithDB(app.capKeyAccountStore, sdk.StoreTypeIAVL, dbs["acc"]) app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeHandler))
app.MountStoreWithDB(app.capKeyPowStore, sdk.StoreTypeIAVL, dbs["pow"])
app.MountStoreWithDB(app.capKeyIBCStore, sdk.StoreTypeIAVL, dbs["ibc"])
app.MountStoreWithDB(app.capKeyStakingStore, sdk.StoreTypeIAVL, dbs["staking"])
// NOTE: Broken until #532 lands
//app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore, app.capKeyStakingStore)
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper))
err := app.LoadLatestVersion(app.capKeyMainStore) err := app.LoadLatestVersion(app.capKeyMainStore)
if err != nil { if err != nil {
cmn.Exit(err.Error()) cmn.Exit(err.Error())
@ -95,41 +99,28 @@ func NewDemocoinApp(logger log.Logger, dbs map[string]dbm.DB) *DemocoinApp {
} }
// custom tx codec // custom tx codec
// TODO: use new go-wire
func MakeCodec() *wire.Codec { func MakeCodec() *wire.Codec {
const msgTypeSend = 0x1 var cdc = wire.NewCodec()
const msgTypeIssue = 0x2
const msgTypeQuiz = 0x3
const msgTypeSetTrend = 0x4
const msgTypeMine = 0x5
const msgTypeIBCTransferMsg = 0x6
const msgTypeIBCReceiveMsg = 0x7
const msgTypeBondMsg = 0x8
const msgTypeUnbondMsg = 0x9
var _ = oldwire.RegisterInterface(
struct{ sdk.Msg }{},
oldwire.ConcreteType{bank.SendMsg{}, msgTypeSend},
oldwire.ConcreteType{bank.IssueMsg{}, msgTypeIssue},
oldwire.ConcreteType{cool.QuizMsg{}, msgTypeQuiz},
oldwire.ConcreteType{cool.SetTrendMsg{}, msgTypeSetTrend},
oldwire.ConcreteType{pow.MineMsg{}, msgTypeMine},
oldwire.ConcreteType{ibc.IBCTransferMsg{}, msgTypeIBCTransferMsg},
oldwire.ConcreteType{ibc.IBCReceiveMsg{}, msgTypeIBCReceiveMsg},
oldwire.ConcreteType{simplestake.BondMsg{}, msgTypeBondMsg},
oldwire.ConcreteType{simplestake.UnbondMsg{}, msgTypeUnbondMsg},
)
const accTypeApp = 0x1 // Register Msgs
var _ = oldwire.RegisterInterface( cdc.RegisterInterface((*sdk.Msg)(nil), nil)
struct{ sdk.Account }{}, cdc.RegisterConcrete(bank.SendMsg{}, "democoin/Send", nil)
oldwire.ConcreteType{&types.AppAccount{}, accTypeApp}, cdc.RegisterConcrete(bank.IssueMsg{}, "democoin/Issue", nil)
) cdc.RegisterConcrete(cool.QuizMsg{}, "democoin/Quiz", nil)
cdc := wire.NewCodec() cdc.RegisterConcrete(cool.SetTrendMsg{}, "democoin/SetTrend", nil)
cdc.RegisterConcrete(pow.MineMsg{}, "democoin/Mine", nil)
cdc.RegisterConcrete(ibc.IBCTransferMsg{}, "democoin/IBCTransferMsg", nil)
cdc.RegisterConcrete(ibc.IBCReceiveMsg{}, "democoin/IBCReceiveMsg", nil)
cdc.RegisterConcrete(simplestake.BondMsg{}, "democoin/BondMsg", nil)
cdc.RegisterConcrete(simplestake.UnbondMsg{}, "democoin/UnbondMsg", nil)
// Register AppAccount
cdc.RegisterInterface((*sdk.Account)(nil), nil)
cdc.RegisterConcrete(&types.AppAccount{}, "democoin/Account", nil)
// Register crypto.
wire.RegisterCrypto(cdc)
// cdc.RegisterInterface((*sdk.Msg)(nil), nil)
// bank.RegisterWire(cdc) // Register bank.[SendMsg,IssueMsg] types.
// crypto.RegisterWire(cdc) // Register crypto.[PubKey,PrivKey,Signature] types.
// ibc.RegisterWire(cdc) // Register ibc.[IBCTransferMsg, IBCReceiveMsg] types.
return cdc return cdc
} }

View File

@ -67,21 +67,15 @@ var (
} }
) )
func loggerAndDBs() (log.Logger, map[string]dbm.DB) { func loggerAndDB() (log.Logger, dbm.DB) {
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app")
dbs := map[string]dbm.DB{ db := dbm.NewMemDB()
"main": dbm.NewMemDB(), return logger, db
"acc": dbm.NewMemDB(),
"pow": dbm.NewMemDB(),
"ibc": dbm.NewMemDB(),
"staking": dbm.NewMemDB(),
}
return logger, dbs
} }
func newDemocoinApp() *DemocoinApp { func newDemocoinApp() *DemocoinApp {
logger, dbs := loggerAndDBs() logger, db := loggerAndDB()
return NewDemocoinApp(logger, dbs) return NewDemocoinApp(logger, db)
} }
//_______________________________________________________________________ //_______________________________________________________________________
@ -106,8 +100,7 @@ func TestMsgs(t *testing.T) {
}}) }})
// just marshal/unmarshal! // just marshal/unmarshal!
cdc := MakeCodec() txBytes, err := bapp.cdc.MarshalBinary(tx)
txBytes, err := cdc.MarshalBinary(tx)
require.NoError(t, err, "i: %v", i) require.NoError(t, err, "i: %v", i)
// Run a Check // Run a Check
@ -124,8 +117,8 @@ func TestMsgs(t *testing.T) {
} }
func TestGenesis(t *testing.T) { func TestGenesis(t *testing.T) {
logger, dbs := loggerAndDBs() logger, db := loggerAndDB()
bapp := NewDemocoinApp(logger, dbs) bapp := NewDemocoinApp(logger, db)
// Construct some genesis bytes to reflect democoin/types/AppAccount // Construct some genesis bytes to reflect democoin/types/AppAccount
pk := crypto.GenPrivKeyEd25519().PubKey() pk := crypto.GenPrivKeyEd25519().PubKey()
@ -158,7 +151,7 @@ func TestGenesis(t *testing.T) {
assert.Equal(t, acc, res1) assert.Equal(t, acc, res1)
// reload app and ensure the account is still there // reload app and ensure the account is still there
bapp = NewDemocoinApp(logger, dbs) bapp = NewDemocoinApp(logger, db)
ctx = bapp.BaseApp.NewContext(true, abci.Header{}) ctx = bapp.BaseApp.NewContext(true, abci.Header{})
res1 = bapp.accountMapper.GetAccount(ctx, baseAcc.Address) res1 = bapp.accountMapper.GetAccount(ctx, baseAcc.Address)
assert.Equal(t, acc, res1) assert.Equal(t, acc, res1)
@ -245,10 +238,9 @@ func TestMineMsg(t *testing.T) {
// Construct genesis state // Construct genesis state
// Construct some genesis bytes to reflect democoin/types/AppAccount // Construct some genesis bytes to reflect democoin/types/AppAccount
coins := sdk.Coins{}
baseAcc := auth.BaseAccount{ baseAcc := auth.BaseAccount{
Address: addr1, Address: addr1,
Coins: coins, Coins: nil,
} }
acc1 := &types.AppAccount{baseAcc, "foobart"} acc1 := &types.AppAccount{baseAcc, "foobart"}
@ -297,10 +289,9 @@ func TestQuizMsg(t *testing.T) {
// Construct genesis state // Construct genesis state
// Construct some genesis bytes to reflect democoin/types/AppAccount // Construct some genesis bytes to reflect democoin/types/AppAccount
coins := sdk.Coins{}
baseAcc := auth.BaseAccount{ baseAcc := auth.BaseAccount{
Address: addr1, Address: addr1,
Coins: coins, Coins: nil,
} }
acc1 := &types.AppAccount{baseAcc, "foobart"} acc1 := &types.AppAccount{baseAcc, "foobart"}

View File

@ -47,34 +47,11 @@ func defaultAppState(args []string, addr sdk.Address, coinDenom string) (json.Ra
} }
func generateApp(rootDir string, logger log.Logger) (abci.Application, error) { func generateApp(rootDir string, logger log.Logger) (abci.Application, error) {
dbMain, err := dbm.NewGoLevelDB("democoin", filepath.Join(rootDir, "data")) db, err := dbm.NewGoLevelDB("democoin", filepath.Join(rootDir, "data"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
dbAcc, err := dbm.NewGoLevelDB("democoin-acc", filepath.Join(rootDir, "data")) bapp := app.NewDemocoinApp(logger, db)
if err != nil {
return nil, err
}
dbPow, err := dbm.NewGoLevelDB("democoin-pow", filepath.Join(rootDir, "data"))
if err != nil {
return nil, err
}
dbIBC, err := dbm.NewGoLevelDB("democoin-ibc", filepath.Join(rootDir, "data"))
if err != nil {
return nil, err
}
dbStaking, err := dbm.NewGoLevelDB("democoin-staking", filepath.Join(rootDir, "data"))
if err != nil {
return nil, err
}
dbs := map[string]dbm.DB{
"main": dbMain,
"acc": dbAcc,
"pow": dbPow,
"ibc": dbIBC,
"staking": dbStaking,
}
bapp := app.NewDemocoinApp(logger, dbs)
return bapp, nil return bapp, nil
} }

View File

@ -15,7 +15,7 @@ var _ sdk.Account = (*AppAccount)(nil)
// extending auth.BaseAccount with custom fields. // extending auth.BaseAccount with custom fields.
// //
// This is compatible with the stock auth.AccountStore, since // This is compatible with the stock auth.AccountStore, since
// auth.AccountStore uses the flexible go-wire library. // auth.AccountStore uses the flexible go-amino library.
type AppAccount struct { type AppAccount struct {
auth.BaseAccount auth.BaseAccount
Name string `json:"name"` Name string `json:"name"`

View File

@ -10,6 +10,7 @@ import (
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/wire"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands"
"github.com/cosmos/cosmos-sdk/examples/democoin/x/cool" "github.com/cosmos/cosmos-sdk/examples/democoin/x/cool"
) )
@ -24,7 +25,7 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command {
return errors.New("You must provide an answer") return errors.New("You must provide an answer")
} }
ctx := context.NewCoreContextFromViper() ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
// get the from address from the name flag // get the from address from the name flag
from, err := ctx.GetFromAddress() from, err := ctx.GetFromAddress()
@ -38,6 +39,12 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command {
// get account name // get account name
name := viper.GetString(client.FlagName) name := viper.GetString(client.FlagName)
// default to next sequence number if none provided
ctx, err = context.EnsureSequence(ctx)
if err != nil {
return err
}
// build and sign the transaction, then broadcast to Tendermint // build and sign the transaction, then broadcast to Tendermint
res, err := ctx.SignBuildBroadcast(name, msg, cdc) res, err := ctx.SignBuildBroadcast(name, msg, cdc)
if err != nil { if err != nil {
@ -60,7 +67,7 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command {
return errors.New("You must provide an answer") return errors.New("You must provide an answer")
} }
ctx := context.NewCoreContextFromViper() ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
// get the from address from the name flag // get the from address from the name flag
from, err := ctx.GetFromAddress() from, err := ctx.GetFromAddress()
@ -71,6 +78,12 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command {
// get account name // get account name
name := viper.GetString(client.FlagName) name := viper.GetString(client.FlagName)
// default to next sequence number if none provided
ctx, err = context.EnsureSequence(ctx)
if err != nil {
return err
}
// create the message // create the message
msg := cool.NewSetTrendMsg(from, args[0]) msg := cool.NewSetTrendMsg(from, args[0])

View File

@ -11,6 +11,7 @@ import (
"github.com/cosmos/cosmos-sdk/examples/democoin/x/pow" "github.com/cosmos/cosmos-sdk/examples/democoin/x/pow"
"github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/wire"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands"
) )
func MineCmd(cdc *wire.Codec) *cobra.Command { func MineCmd(cdc *wire.Codec) *cobra.Command {
@ -24,7 +25,7 @@ func MineCmd(cdc *wire.Codec) *cobra.Command {
// get from address and parse arguments // get from address and parse arguments
ctx := context.NewCoreContextFromViper() ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
from, err := ctx.GetFromAddress() from, err := ctx.GetFromAddress()
if err != nil { if err != nil {
@ -53,6 +54,12 @@ func MineCmd(cdc *wire.Codec) *cobra.Command {
// get account name // get account name
name := ctx.FromAddressName name := ctx.FromAddressName
// default to next sequence number if none provided
ctx, err = context.EnsureSequence(ctx)
if err != nil {
return err
}
// build and sign the transaction, then broadcast to Tendermint // build and sign the transaction, then broadcast to Tendermint
res, err := ctx.SignBuildBroadcast(name, msg, cdc) res, err := ctx.SignBuildBroadcast(name, msg, cdc)
if err != nil { if err != nil {

View File

@ -8,14 +8,17 @@ import (
abci "github.com/tendermint/abci/types" abci "github.com/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
wire "github.com/cosmos/cosmos-sdk/wire"
auth "github.com/cosmos/cosmos-sdk/x/auth" auth "github.com/cosmos/cosmos-sdk/x/auth"
bank "github.com/cosmos/cosmos-sdk/x/bank" bank "github.com/cosmos/cosmos-sdk/x/bank"
) )
func TestPowHandler(t *testing.T) { func TestPowHandler(t *testing.T) {
ms, capKey := setupMultiStore() ms, capKey := setupMultiStore()
cdc := wire.NewCodec()
auth.RegisterBaseAccount(cdc)
am := auth.NewAccountMapper(capKey, &auth.BaseAccount{}) am := auth.NewAccountMapper(cdc, capKey, &auth.BaseAccount{})
ctx := sdk.NewContext(ms, abci.Header{}, false, nil) ctx := sdk.NewContext(ms, abci.Header{}, false, nil)
config := NewPowConfig("pow", int64(1)) config := NewPowConfig("pow", int64(1))
ck := bank.NewCoinKeeper(am) ck := bank.NewCoinKeeper(am)

View File

@ -10,6 +10,7 @@ import (
"github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
auth "github.com/cosmos/cosmos-sdk/x/auth" auth "github.com/cosmos/cosmos-sdk/x/auth"
bank "github.com/cosmos/cosmos-sdk/x/bank" bank "github.com/cosmos/cosmos-sdk/x/bank"
) )
@ -27,8 +28,10 @@ func setupMultiStore() (sdk.MultiStore, *sdk.KVStoreKey) {
func TestPowKeeperGetSet(t *testing.T) { func TestPowKeeperGetSet(t *testing.T) {
ms, capKey := setupMultiStore() ms, capKey := setupMultiStore()
cdc := wire.NewCodec()
auth.RegisterBaseAccount(cdc)
am := auth.NewAccountMapper(capKey, &auth.BaseAccount{}) am := auth.NewAccountMapper(cdc, capKey, &auth.BaseAccount{})
ctx := sdk.NewContext(ms, abci.Header{}, false, nil) ctx := sdk.NewContext(ms, abci.Header{}, false, nil)
config := NewPowConfig("pow", int64(1)) config := NewPowConfig("pow", int64(1))
ck := bank.NewCoinKeeper(am) ck := bank.NewCoinKeeper(am)

View File

@ -6,6 +6,7 @@ import (
"io/ioutil" "io/ioutil"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/tendermint/go-crypto/keys" "github.com/tendermint/go-crypto/keys"
@ -13,6 +14,7 @@ import (
cfg "github.com/tendermint/tendermint/config" cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/p2p"
tmtypes "github.com/tendermint/tendermint/types" tmtypes "github.com/tendermint/tendermint/types"
pvm "github.com/tendermint/tendermint/types/priv_validator"
cmn "github.com/tendermint/tmlibs/common" cmn "github.com/tendermint/tmlibs/common"
dbm "github.com/tendermint/tmlibs/db" dbm "github.com/tendermint/tmlibs/db"
) )
@ -96,7 +98,7 @@ func (c initCmd) run(cmd *cobra.Command, args []string) error {
return err return err
} }
testnetInfo.NodeID = nodeKey.ID() testnetInfo.NodeID = nodeKey.ID()
out, err := json.MarshalIndent(testnetInfo, "", " ") out, err := wire.MarshalJSONIndent(cdc, testnetInfo)
if err != nil { if err != nil {
return err return err
} }
@ -109,12 +111,12 @@ func (c initCmd) run(cmd *cobra.Command, args []string) error {
func (c initCmd) initTendermintFiles(config *cfg.Config, info *testnetInformation) error { func (c initCmd) initTendermintFiles(config *cfg.Config, info *testnetInformation) error {
// private validator // private validator
privValFile := config.PrivValidatorFile() privValFile := config.PrivValidatorFile()
var privValidator *tmtypes.PrivValidatorFS var privValidator *pvm.FilePV
if cmn.FileExists(privValFile) { if cmn.FileExists(privValFile) {
privValidator = tmtypes.LoadPrivValidatorFS(privValFile) privValidator = pvm.LoadFilePV(privValFile)
c.context.Logger.Info("Found private validator", "path", privValFile) c.context.Logger.Info("Found private validator", "path", privValFile)
} else { } else {
privValidator = tmtypes.GenPrivValidatorFS(privValFile) privValidator = pvm.GenFilePV(privValFile)
privValidator.Save() privValidator.Save()
c.context.Logger.Info("Generated private validator", "path", privValFile) c.context.Logger.Info("Generated private validator", "path", privValFile)
} }
@ -193,13 +195,13 @@ func addGenesisState(filename string, appState json.RawMessage) error {
} }
var doc GenesisDoc var doc GenesisDoc
err = json.Unmarshal(bz, &doc) err = cdc.UnmarshalJSON(bz, &doc)
if err != nil { if err != nil {
return err return err
} }
doc["app_state"] = appState doc["app_state"] = appState
out, err := json.MarshalIndent(doc, "", " ") out, err := wire.MarshalJSONIndent(cdc, doc)
if err != nil { if err != nil {
return err return err
} }

View File

@ -11,7 +11,7 @@ import (
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
"github.com/tendermint/tendermint/node" "github.com/tendermint/tendermint/node"
"github.com/tendermint/tendermint/proxy" "github.com/tendermint/tendermint/proxy"
"github.com/tendermint/tendermint/types" pvm "github.com/tendermint/tendermint/types/priv_validator"
cmn "github.com/tendermint/tmlibs/common" cmn "github.com/tendermint/tmlibs/common"
"github.com/tendermint/tmlibs/log" "github.com/tendermint/tmlibs/log"
) )
@ -95,7 +95,7 @@ func (s startCmd) startInProcess() error {
// Create & start tendermint node // Create & start tendermint node
n, err := node.NewNode(cfg, n, err := node.NewNode(cfg,
types.LoadOrGenPrivValidatorFS(cfg.PrivValidatorFile()), pvm.LoadOrGenFilePV(cfg.PrivValidatorFile()),
proxy.NewLocalClientCreator(app), proxy.NewLocalClientCreator(app),
node.DefaultGenesisDocProviderFunc(cfg), node.DefaultGenesisDocProviderFunc(cfg),
node.DefaultDBProvider, node.DefaultDBProvider,

View File

@ -5,10 +5,9 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/tendermint/go-wire/data"
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
"github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/p2p"
"github.com/tendermint/tendermint/types" pvm "github.com/tendermint/tendermint/types/priv_validator"
) )
// ShowNodeIDCmd - ported from Tendermint, dump node ID to stdout // ShowNodeIDCmd - ported from Tendermint, dump node ID to stdout
@ -53,8 +52,8 @@ type showValidator struct {
func (s showValidator) run(cmd *cobra.Command, args []string) error { func (s showValidator) run(cmd *cobra.Command, args []string) error {
cfg := s.context.Config cfg := s.context.Config
privValidator := types.LoadOrGenPrivValidatorFS(cfg.PrivValidatorFile()) privValidator := pvm.LoadOrGenFilePV(cfg.PrivValidatorFile())
pubKeyJSONBytes, err := data.ToJSON(privValidator.PubKey) pubKeyJSONBytes, err := cdc.MarshalJSON(privValidator.PubKey)
if err != nil { if err != nil {
return err return err
} }

12
server/wire.go Normal file
View File

@ -0,0 +1,12 @@
package server
import (
"github.com/cosmos/cosmos-sdk/wire"
)
var cdc *wire.Codec
func init() {
cdc = wire.NewCodec()
wire.RegisterCrypto(cdc)
}

View File

@ -5,6 +5,7 @@ import (
"sort" "sort"
"sync" "sync"
sdk "github.com/cosmos/cosmos-sdk/types"
cmn "github.com/tendermint/tmlibs/common" cmn "github.com/tendermint/tmlibs/common"
) )
@ -134,6 +135,16 @@ func (ci *cacheKVStore) ReverseIterator(start, end []byte) Iterator {
return ci.iterator(start, end, false) return ci.iterator(start, end, false)
} }
// Implements KVStore.
func (ci *cacheKVStore) SubspaceIterator(prefix []byte) Iterator {
return ci.iterator(prefix, sdk.PrefixEndBytes(prefix), true)
}
// Implements KVStore.
func (ci *cacheKVStore) ReverseSubspaceIterator(prefix []byte) Iterator {
return ci.iterator(prefix, sdk.PrefixEndBytes(prefix), false)
}
func (ci *cacheKVStore) iterator(start, end []byte, ascending bool) Iterator { func (ci *cacheKVStore) iterator(start, end []byte, ascending bool) Iterator {
var parent, cache Iterator var parent, cache Iterator
if ascending { if ascending {

View File

@ -19,5 +19,13 @@ func (dsa dbStoreAdapter) CacheWrap() CacheWrap {
return NewCacheKVStore(dsa) return NewCacheKVStore(dsa)
} }
func (dsa dbStoreAdapter) SubspaceIterator(prefix []byte) Iterator {
return dsa.Iterator(prefix, sdk.PrefixEndBytes(prefix))
}
func (dsa dbStoreAdapter) ReverseSubspaceIterator(prefix []byte) Iterator {
return dsa.ReverseIterator(prefix, sdk.PrefixEndBytes(prefix))
}
// dbm.DB implements KVStore so we can CacheKVStore it. // dbm.DB implements KVStore so we can CacheKVStore it.
var _ KVStore = dbStoreAdapter{dbm.DB(nil)} var _ KVStore = dbStoreAdapter{dbm.DB(nil)}

View File

@ -119,18 +119,21 @@ func (st *iavlStore) Iterator(start, end []byte) Iterator {
return newIAVLIterator(st.tree.Tree(), start, end, true) return newIAVLIterator(st.tree.Tree(), start, end, true)
} }
func (st *iavlStore) Subspace(prefix []byte) Iterator { // Implements KVStore.
end := make([]byte, len(prefix))
copy(end, prefix)
end[len(end)-1]++
return st.Iterator(prefix, end)
}
// Implements IterKVStore.
func (st *iavlStore) ReverseIterator(start, end []byte) Iterator { func (st *iavlStore) ReverseIterator(start, end []byte) Iterator {
return newIAVLIterator(st.tree.Tree(), start, end, false) return newIAVLIterator(st.tree.Tree(), start, end, false)
} }
// Implements KVStore.
func (st *iavlStore) SubspaceIterator(prefix []byte) Iterator {
return st.Iterator(prefix, sdk.PrefixEndBytes(prefix))
}
// Implements KVStore.
func (st *iavlStore) ReverseSubspaceIterator(prefix []byte) Iterator {
return st.ReverseIterator(prefix, sdk.PrefixEndBytes(prefix))
}
// Query implements ABCI interface, allows queries // Query implements ABCI interface, allows queries
// //
// by default we will return from (latest height -1), // by default we will return from (latest height -1),
@ -339,6 +342,9 @@ func (iter *iavlIterator) assertIsValid() {
//---------------------------------------- //----------------------------------------
func cp(bz []byte) (ret []byte) { func cp(bz []byte) (ret []byte) {
if bz == nil {
return nil
}
ret = make([]byte, len(bz)) ret = make([]byte, len(bz))
copy(ret, bz) copy(ret, bz)
return ret return ret

View File

@ -73,16 +73,74 @@ func TestIAVLIterator(t *testing.T) {
iavlStore := newIAVLStore(tree, numHistory) iavlStore := newIAVLStore(tree, numHistory)
iter := iavlStore.Iterator([]byte("aloha"), []byte("hellz")) iter := iavlStore.Iterator([]byte("aloha"), []byte("hellz"))
expected := []string{"aloha", "hello"} expected := []string{"aloha", "hello"}
for i := 0; iter.Valid(); iter.Next() { var i int
for i = 0; iter.Valid(); iter.Next() {
expectedKey := expected[i] expectedKey := expected[i]
key, value := iter.Key(), iter.Value() key, value := iter.Key(), iter.Value()
assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, key, expectedKey)
assert.EqualValues(t, value, treeData[expectedKey]) assert.EqualValues(t, value, treeData[expectedKey])
i += 1 i += 1
} }
assert.Equal(t, len(expected), i)
iter = iavlStore.Iterator([]byte("golang"), []byte("rocks"))
expected = []string{"hello"}
for i = 0; iter.Valid(); iter.Next() {
expectedKey := expected[i]
key, value := iter.Key(), iter.Value()
assert.EqualValues(t, key, expectedKey)
assert.EqualValues(t, value, treeData[expectedKey])
i += 1
}
assert.Equal(t, len(expected), i)
iter = iavlStore.Iterator(nil, []byte("golang"))
expected = []string{"aloha"}
for i = 0; iter.Valid(); iter.Next() {
expectedKey := expected[i]
key, value := iter.Key(), iter.Value()
assert.EqualValues(t, key, expectedKey)
assert.EqualValues(t, value, treeData[expectedKey])
i += 1
}
assert.Equal(t, len(expected), i)
iter = iavlStore.Iterator(nil, []byte("shalom"))
expected = []string{"aloha", "hello"}
for i = 0; iter.Valid(); iter.Next() {
expectedKey := expected[i]
key, value := iter.Key(), iter.Value()
assert.EqualValues(t, key, expectedKey)
assert.EqualValues(t, value, treeData[expectedKey])
i += 1
}
assert.Equal(t, len(expected), i)
iter = iavlStore.Iterator(nil, nil)
expected = []string{"aloha", "hello"}
for i = 0; iter.Valid(); iter.Next() {
expectedKey := expected[i]
key, value := iter.Key(), iter.Value()
assert.EqualValues(t, key, expectedKey)
assert.EqualValues(t, value, treeData[expectedKey])
i += 1
}
assert.Equal(t, len(expected), i)
iter = iavlStore.Iterator([]byte("golang"), nil)
expected = []string{"hello"}
for i = 0; iter.Valid(); iter.Next() {
expectedKey := expected[i]
key, value := iter.Key(), iter.Value()
assert.EqualValues(t, key, expectedKey)
assert.EqualValues(t, value, treeData[expectedKey])
i += 1
}
assert.Equal(t, len(expected), i)
} }
func TestIAVLSubspace(t *testing.T) { func TestIAVLSubspaceIterator(t *testing.T) {
db := dbm.NewMemDB() db := dbm.NewMemDB()
tree, _ := newTree(t, db) tree, _ := newTree(t, db)
iavlStore := newIAVLStore(tree, numHistory) iavlStore := newIAVLStore(tree, numHistory)
@ -90,16 +148,114 @@ func TestIAVLSubspace(t *testing.T) {
iavlStore.Set([]byte("test1"), []byte("test1")) iavlStore.Set([]byte("test1"), []byte("test1"))
iavlStore.Set([]byte("test2"), []byte("test2")) iavlStore.Set([]byte("test2"), []byte("test2"))
iavlStore.Set([]byte("test3"), []byte("test3")) iavlStore.Set([]byte("test3"), []byte("test3"))
iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(0)}, []byte("test4"))
iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(1)}, []byte("test4"))
iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(255)}, []byte("test4"))
iavlStore.Set([]byte{byte(255), byte(255), byte(0)}, []byte("test4"))
iavlStore.Set([]byte{byte(255), byte(255), byte(1)}, []byte("test4"))
iavlStore.Set([]byte{byte(255), byte(255), byte(255)}, []byte("test4"))
iter := iavlStore.Subspace([]byte("test")) i := 0
iter := iavlStore.SubspaceIterator([]byte("test"))
expected := []string{"test1", "test2", "test3"} expected := []string{"test1", "test2", "test3"}
for i := 0; iter.Valid(); iter.Next() { for i = 0; iter.Valid(); iter.Next() {
expectedKey := expected[i] expectedKey := expected[i]
key, value := iter.Key(), iter.Value() key, value := iter.Key(), iter.Value()
assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, key, expectedKey)
assert.EqualValues(t, value, expectedKey) assert.EqualValues(t, value, expectedKey)
i += 1 i += 1
} }
assert.Equal(t, len(expected), i)
iter = iavlStore.SubspaceIterator([]byte{byte(55), byte(255), byte(255)})
expected2 := [][]byte{
[]byte{byte(55), byte(255), byte(255), byte(0)},
[]byte{byte(55), byte(255), byte(255), byte(1)},
[]byte{byte(55), byte(255), byte(255), byte(255)},
}
for i = 0; iter.Valid(); iter.Next() {
expectedKey := expected2[i]
key, value := iter.Key(), iter.Value()
assert.EqualValues(t, key, expectedKey)
assert.EqualValues(t, value, []byte("test4"))
i += 1
}
assert.Equal(t, len(expected), i)
iter = iavlStore.SubspaceIterator([]byte{byte(255), byte(255)})
expected2 = [][]byte{
[]byte{byte(255), byte(255), byte(0)},
[]byte{byte(255), byte(255), byte(1)},
[]byte{byte(255), byte(255), byte(255)},
}
for i = 0; iter.Valid(); iter.Next() {
expectedKey := expected2[i]
key, value := iter.Key(), iter.Value()
assert.EqualValues(t, key, expectedKey)
assert.EqualValues(t, value, []byte("test4"))
i += 1
}
assert.Equal(t, len(expected), i)
}
func TestIAVLReverseSubspaceIterator(t *testing.T) {
db := dbm.NewMemDB()
tree, _ := newTree(t, db)
iavlStore := newIAVLStore(tree, numHistory)
iavlStore.Set([]byte("test1"), []byte("test1"))
iavlStore.Set([]byte("test2"), []byte("test2"))
iavlStore.Set([]byte("test3"), []byte("test3"))
iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(0)}, []byte("test4"))
iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(1)}, []byte("test4"))
iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(255)}, []byte("test4"))
iavlStore.Set([]byte{byte(255), byte(255), byte(0)}, []byte("test4"))
iavlStore.Set([]byte{byte(255), byte(255), byte(1)}, []byte("test4"))
iavlStore.Set([]byte{byte(255), byte(255), byte(255)}, []byte("test4"))
i := 0
iter := iavlStore.ReverseSubspaceIterator([]byte("test"))
expected := []string{"test3", "test2", "test1"}
for i = 0; iter.Valid(); iter.Next() {
expectedKey := expected[i]
key, value := iter.Key(), iter.Value()
assert.EqualValues(t, key, expectedKey)
assert.EqualValues(t, value, expectedKey)
i += 1
}
assert.Equal(t, len(expected), i)
iter = iavlStore.ReverseSubspaceIterator([]byte{byte(55), byte(255), byte(255)})
expected2 := [][]byte{
[]byte{byte(55), byte(255), byte(255), byte(255)},
[]byte{byte(55), byte(255), byte(255), byte(1)},
[]byte{byte(55), byte(255), byte(255), byte(0)},
}
for i = 0; iter.Valid(); iter.Next() {
expectedKey := expected2[i]
key, value := iter.Key(), iter.Value()
assert.EqualValues(t, key, expectedKey)
assert.EqualValues(t, value, []byte("test4"))
i += 1
}
assert.Equal(t, len(expected), i)
iter = iavlStore.ReverseSubspaceIterator([]byte{byte(255), byte(255)})
expected2 = [][]byte{
[]byte{byte(255), byte(255), byte(255)},
[]byte{byte(255), byte(255), byte(1)},
[]byte{byte(255), byte(255), byte(0)},
}
for i = 0; iter.Valid(); iter.Next() {
expectedKey := expected2[i]
key, value := iter.Key(), iter.Value()
assert.EqualValues(t, key, expectedKey)
assert.EqualValues(t, value, []byte("test4"))
i += 1
}
assert.Equal(t, len(expected), i)
} }
func TestIAVLStoreQuery(t *testing.T) { func TestIAVLStoreQuery(t *testing.T) {

View File

@ -56,8 +56,9 @@ func (rs *rootMultiStore) MountStoreWithDB(key StoreKey, typ StoreType, db dbm.D
panic(fmt.Sprintf("rootMultiStore duplicate store key %v", key)) panic(fmt.Sprintf("rootMultiStore duplicate store key %v", key))
} }
rs.storesParams[key] = storeParams{ rs.storesParams[key] = storeParams{
db: db, key: key,
typ: typ, typ: typ,
db: db,
} }
rs.keysByName[key.Name()] = key rs.keysByName[key.Name()] = key
} }
@ -244,9 +245,11 @@ func parsePath(path string) (storeName string, subpath string, err sdk.Error) {
//---------------------------------------- //----------------------------------------
func (rs *rootMultiStore) loadCommitStoreFromParams(id CommitID, params storeParams) (store CommitStore, err error) { func (rs *rootMultiStore) loadCommitStoreFromParams(id CommitID, params storeParams) (store CommitStore, err error) {
db := rs.db var db dbm.DB
if params.db != nil { if params.db != nil {
db = params.db db = dbm.NewPrefixDB(params.db, []byte("s/_/"))
} else {
db = dbm.NewPrefixDB(rs.db, []byte("s/k:"+params.key.Name()+"/"))
} }
switch params.typ { switch params.typ {
case sdk.StoreTypeMulti: case sdk.StoreTypeMulti:
@ -276,6 +279,7 @@ func (rs *rootMultiStore) nameToKey(name string) StoreKey {
// storeParams // storeParams
type storeParams struct { type storeParams struct {
key StoreKey
db dbm.DB db dbm.DB
typ StoreType typ StoreType
} }
@ -375,10 +379,11 @@ func commitStores(version int64, storeMap map[StoreKey]CommitStore) commitInfo {
storeInfos = append(storeInfos, si) storeInfos = append(storeInfos, si)
} }
return commitInfo{ ci := commitInfo{
Version: version, Version: version,
StoreInfos: storeInfos, StoreInfos: storeInfos,
} }
return ci
} }
// Gets commitInfo from disk. // Gets commitInfo from disk.

View File

@ -11,17 +11,22 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
) )
const useDebugDB = false
func TestMultistoreCommitLoad(t *testing.T) { func TestMultistoreCommitLoad(t *testing.T) {
db := dbm.NewMemDB() var db dbm.DB = dbm.NewMemDB()
if useDebugDB {
db = dbm.NewDebugDB("CMS", db)
}
store := newMultiStoreWithMounts(db) store := newMultiStoreWithMounts(db)
err := store.LoadLatestVersion() err := store.LoadLatestVersion()
assert.Nil(t, err) assert.Nil(t, err)
// new store has empty last commit // New store has empty last commit.
commitID := CommitID{} commitID := CommitID{}
checkStore(t, store, commitID, commitID) checkStore(t, store, commitID, commitID)
// make sure we can get stores by name // Make sure we can get stores by name.
s1 := store.getStoreByName("store1") s1 := store.getStoreByName("store1")
assert.NotNil(t, s1) assert.NotNil(t, s1)
s3 := store.getStoreByName("store3") s3 := store.getStoreByName("store3")
@ -29,7 +34,7 @@ func TestMultistoreCommitLoad(t *testing.T) {
s77 := store.getStoreByName("store77") s77 := store.getStoreByName("store77")
assert.Nil(t, s77) assert.Nil(t, s77)
// make a few commits and check them // Make a few commits and check them.
nCommits := int64(3) nCommits := int64(3)
for i := int64(0); i < nCommits; i++ { for i := int64(0); i < nCommits; i++ {
commitID = store.Commit() commitID = store.Commit()
@ -37,19 +42,19 @@ func TestMultistoreCommitLoad(t *testing.T) {
checkStore(t, store, expectedCommitID, commitID) checkStore(t, store, expectedCommitID, commitID)
} }
// Load the latest multistore again and check version // Load the latest multistore again and check version.
store = newMultiStoreWithMounts(db) store = newMultiStoreWithMounts(db)
err = store.LoadLatestVersion() err = store.LoadLatestVersion()
assert.Nil(t, err) assert.Nil(t, err)
commitID = getExpectedCommitID(store, nCommits) commitID = getExpectedCommitID(store, nCommits)
checkStore(t, store, commitID, commitID) checkStore(t, store, commitID, commitID)
// commit and check version // Commit and check version.
commitID = store.Commit() commitID = store.Commit()
expectedCommitID := getExpectedCommitID(store, nCommits+1) expectedCommitID := getExpectedCommitID(store, nCommits+1)
checkStore(t, store, expectedCommitID, commitID) checkStore(t, store, expectedCommitID, commitID)
// Load an older multistore and check version // Load an older multistore and check version.
ver := nCommits - 1 ver := nCommits - 1
store = newMultiStoreWithMounts(db) store = newMultiStoreWithMounts(db)
err = store.LoadVersion(ver) err = store.LoadVersion(ver)
@ -62,8 +67,8 @@ func TestMultistoreCommitLoad(t *testing.T) {
expectedCommitID = getExpectedCommitID(store, ver+1) expectedCommitID = getExpectedCommitID(store, ver+1)
checkStore(t, store, expectedCommitID, commitID) checkStore(t, store, expectedCommitID, commitID)
// XXX: confirm old commit is overwritten and // XXX: confirm old commit is overwritten and we have rolled back
// we have rolled back LatestVersion // LatestVersion
store = newMultiStoreWithMounts(db) store = newMultiStoreWithMounts(db)
err = store.LoadLatestVersion() err = store.LoadLatestVersion()
assert.Nil(t, err) assert.Nil(t, err)
@ -104,23 +109,23 @@ func TestMultiStoreQuery(t *testing.T) {
cid := multi.Commit() cid := multi.Commit()
// make sure we can get by name // Make sure we can get by name.
garbage := multi.getStoreByName("bad-name") garbage := multi.getStoreByName("bad-name")
assert.Nil(t, garbage) assert.Nil(t, garbage)
// set and commit data in one store // Set and commit data in one store.
store1 := multi.getStoreByName("store1").(KVStore) store1 := multi.getStoreByName("store1").(KVStore)
store1.Set(k, v) store1.Set(k, v)
// and another // ... and another.
store2 := multi.getStoreByName("store2").(KVStore) store2 := multi.getStoreByName("store2").(KVStore)
store2.Set(k2, v2) store2.Set(k2, v2)
// commit the multistore // Commit the multistore.
cid = multi.Commit() cid = multi.Commit()
ver := cid.Version ver := cid.Version
// bad path // Test bad path.
query := abci.RequestQuery{Path: "/key", Data: k, Height: ver} query := abci.RequestQuery{Path: "/key", Data: k, Height: ver}
qres := multi.Query(query) qres := multi.Query(query)
assert.Equal(t, uint32(sdk.CodeUnknownRequest), qres.Code) assert.Equal(t, uint32(sdk.CodeUnknownRequest), qres.Code)
@ -129,25 +134,25 @@ func TestMultiStoreQuery(t *testing.T) {
qres = multi.Query(query) qres = multi.Query(query)
assert.Equal(t, uint32(sdk.CodeUnknownRequest), qres.Code) assert.Equal(t, uint32(sdk.CodeUnknownRequest), qres.Code)
// invalid store name // Test invalid store name.
query.Path = "/garbage/key" query.Path = "/garbage/key"
qres = multi.Query(query) qres = multi.Query(query)
assert.Equal(t, uint32(sdk.CodeUnknownRequest), qres.Code) assert.Equal(t, uint32(sdk.CodeUnknownRequest), qres.Code)
// valid query with data // Test valid query with data.
query.Path = "/store1/key" query.Path = "/store1/key"
qres = multi.Query(query) qres = multi.Query(query)
assert.Equal(t, uint32(sdk.CodeOK), qres.Code) assert.Equal(t, uint32(sdk.CodeOK), qres.Code)
assert.Equal(t, v, qres.Value) assert.Equal(t, v, qres.Value)
// valid but empty // Test valid but empty query.
query.Path = "/store2/key" query.Path = "/store2/key"
query.Prove = true query.Prove = true
qres = multi.Query(query) qres = multi.Query(query)
assert.Equal(t, uint32(sdk.CodeOK), qres.Code) assert.Equal(t, uint32(sdk.CodeOK), qres.Code)
assert.Nil(t, qres.Value) assert.Nil(t, qres.Value)
// store2 data // Test store2 data.
query.Data = k2 query.Data = k2
qres = multi.Query(query) qres = multi.Query(query)
assert.Equal(t, uint32(sdk.CodeOK), qres.Code) assert.Equal(t, uint32(sdk.CodeOK), qres.Code)

View File

@ -110,7 +110,7 @@ func (coins Coins) IsValid() bool {
// Plus combines two sets of coins // Plus combines two sets of coins
// CONTRACT: Plus will never return Coins where one Coin has a 0 amount. // CONTRACT: Plus will never return Coins where one Coin has a 0 amount.
func (coins Coins) Plus(coinsB Coins) Coins { func (coins Coins) Plus(coinsB Coins) Coins {
sum := []Coin{} sum := ([]Coin)(nil)
indexA, indexB := 0, 0 indexA, indexB := 0, 0
lenA, lenB := len(coins), len(coinsB) lenA, lenB := len(coins), len(coinsB)
for { for {

View File

@ -201,8 +201,8 @@ func TestPlusCoins(t *testing.T) {
}{ }{
{Coins{{"A", 1}, {"B", 1}}, Coins{{"A", 1}, {"B", 1}}, Coins{{"A", 2}, {"B", 2}}}, {Coins{{"A", 1}, {"B", 1}}, Coins{{"A", 1}, {"B", 1}}, Coins{{"A", 2}, {"B", 2}}},
{Coins{{"A", 0}, {"B", 1}}, Coins{{"A", 0}, {"B", 0}}, Coins{{"B", 1}}}, {Coins{{"A", 0}, {"B", 1}}, Coins{{"A", 0}, {"B", 0}}, Coins{{"B", 1}}},
{Coins{{"A", 0}, {"B", 0}}, Coins{{"A", 0}, {"B", 0}}, Coins{}}, {Coins{{"A", 0}, {"B", 0}}, Coins{{"A", 0}, {"B", 0}}, Coins(nil)},
{Coins{{"A", 1}, {"B", 0}}, Coins{{"A", -1}, {"B", 0}}, Coins{}}, {Coins{{"A", 1}, {"B", 0}}, Coins{{"A", -1}, {"B", 0}}, Coins(nil)},
{Coins{{"A", -1}, {"B", 0}}, Coins{{"A", 0}, {"B", 0}}, Coins{{"A", -1}}}, {Coins{{"A", -1}, {"B", 0}}, Coins{{"A", 0}, {"B", 0}}, Coins{{"A", -1}}},
} }

View File

@ -171,6 +171,14 @@ func (c Context) WithTxBytes(txBytes []byte) Context {
return c.withValue(contextKeyTxBytes, txBytes) return c.withValue(contextKeyTxBytes, txBytes)
} }
// Cache the multistore and return a new cached context. The cached context is
// written to the context when writeCache is called.
func (c Context) CacheContext() (cc Context, writeCache func()) {
cms := c.multiStore().CacheMultiStore()
cc = c.WithMultiStore(cms)
return cc, cms.Write
}
//---------------------------------------- //----------------------------------------
// thePast // thePast

View File

@ -3,6 +3,11 @@ package types_test
import ( import (
"testing" "testing"
"github.com/stretchr/testify/assert"
dbm "github.com/tendermint/tmlibs/db"
"github.com/cosmos/cosmos-sdk/store"
"github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/abci/types" abci "github.com/tendermint/abci/types"
) )
@ -18,3 +23,39 @@ func TestContextGetOpShouldNeverPanic(t *testing.T) {
_, _ = ctx.GetOp(index) _, _ = ctx.GetOp(index)
} }
} }
func defaultContext(key types.StoreKey) types.Context {
db := dbm.NewMemDB()
cms := store.NewCommitMultiStore(db)
cms.MountStoreWithDB(key, types.StoreTypeIAVL, db)
cms.LoadLatestVersion()
ctx := types.NewContext(cms, abci.Header{}, false, nil)
return ctx
}
func TestCacheContext(t *testing.T) {
key := types.NewKVStoreKey(t.Name())
k1 := []byte("hello")
v1 := []byte("world")
k2 := []byte("key")
v2 := []byte("value")
ctx := defaultContext(key)
store := ctx.KVStore(key)
store.Set(k1, v1)
assert.Equal(t, v1, store.Get(k1))
assert.Nil(t, store.Get(k2))
cctx, write := ctx.CacheContext()
cstore := cctx.KVStore(key)
assert.Equal(t, v1, cstore.Get(k1))
assert.Nil(t, cstore.Get(k2))
cstore.Set(k2, v2)
assert.Equal(t, v2, cstore.Get(k2))
assert.Nil(t, store.Get(k2))
write()
assert.Equal(t, v2, store.Get(k2))
}

View File

@ -3,5 +3,8 @@ package types
// core function variable which application runs for transactions // core function variable which application runs for transactions
type Handler func(ctx Context, msg Msg) Result type Handler func(ctx Context, msg Msg) Result
// core function variable which application runs to handle fees
type FeeHandler func(ctx Context, tx Tx, fee Coins)
// If newCtx.IsZero(), ctx is used instead. // If newCtx.IsZero(), ctx is used instead.
type AnteHandler func(ctx Context, tx Tx) (newCtx Context, result Result, abort bool) type AnteHandler func(ctx Context, tx Tx) (newCtx Context, result Result, abort bool)

View File

@ -111,6 +111,14 @@ type KVStore interface {
// CONTRACT: No writes may happen within a domain while an iterator exists over it. // CONTRACT: No writes may happen within a domain while an iterator exists over it.
ReverseIterator(start, end []byte) Iterator ReverseIterator(start, end []byte) Iterator
// Iterator over all the keys with a certain prefix in ascending order.
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
SubspaceIterator(prefix []byte) Iterator
// Iterator over all the keys with a certain prefix in descending order.
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
ReverseSubspaceIterator(prefix []byte) Iterator
// TODO Not yet implemented. // TODO Not yet implemented.
// CreateSubKVStore(key *storeKey) (KVStore, error) // CreateSubKVStore(key *storeKey) (KVStore, error)
@ -222,3 +230,29 @@ func (key *KVStoreKey) Name() string {
func (key *KVStoreKey) String() string { func (key *KVStoreKey) String() string {
return fmt.Sprintf("KVStoreKey{%p, %s}", key, key.name) return fmt.Sprintf("KVStoreKey{%p, %s}", key, key.name)
} }
// PrefixEndBytes returns the []byte that would end a
// range query for all []byte with a certain prefix
// Deals with last byte of prefix being FF without overflowing
func PrefixEndBytes(prefix []byte) []byte {
if prefix == nil {
return nil
}
end := make([]byte, len(prefix))
copy(end, prefix)
for {
if end[len(end)-1] != byte(255) {
end[len(end)-1]++
break
} else {
end = end[:len(end)-1]
if len(end) == 0 {
end = nil
break
}
}
}
return end
}

29
types/store_test.go Normal file
View File

@ -0,0 +1,29 @@
package types
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestPrefixEndBytes(t *testing.T) {
assert := assert.New(t)
var testCases = []struct {
prefix []byte
expected []byte
}{
{[]byte{byte(55), byte(255), byte(255), byte(0)}, []byte{byte(55), byte(255), byte(255), byte(1)}},
{[]byte{byte(55), byte(255), byte(255), byte(15)}, []byte{byte(55), byte(255), byte(255), byte(16)}},
{[]byte{byte(55), byte(200), byte(255)}, []byte{byte(55), byte(201)}},
{[]byte{byte(55), byte(255), byte(255)}, []byte{byte(56)}},
{[]byte{byte(255), byte(255), byte(255)}, nil},
{[]byte{byte(255)}, nil},
{nil, nil},
}
for _, test := range testCases {
end := PrefixEndBytes(test.prefix)
assert.Equal(test.expected, end)
}
}

View File

@ -6,10 +6,10 @@ package version
// TODO improve // TODO improve
const Maj = "0" const Maj = "0"
const Min = "14" const Min = "15"
const Fix = "1" const Fix = "0"
const Version = "0.14.1" const Version = "0.15.0"
// GitCommit set by build flags // GitCommit set by build flags
var GitCommit = "" var GitCommit = ""

View File

@ -2,54 +2,33 @@ package wire
import ( import (
"bytes" "bytes"
"reflect" "encoding/json"
"github.com/tendermint/go-wire" "github.com/tendermint/go-amino"
"github.com/tendermint/go-crypto"
) )
type Codec struct{} type Codec = amino.Codec
func NewCodec() *Codec { func NewCodec() *Codec {
return &Codec{} cdc := amino.NewCodec()
return cdc
} }
func (cdc *Codec) MarshalBinary(o interface{}) ([]byte, error) {
w, n, err := new(bytes.Buffer), new(int), new(error)
wire.WriteBinary(o, w, n, err)
return w.Bytes(), *err
}
func (cdc *Codec) UnmarshalBinary(bz []byte, o interface{}) error {
r, n, err := bytes.NewBuffer(bz), new(int), new(error)
rv := reflect.ValueOf(o)
if rv.Kind() == reflect.Ptr {
wire.ReadBinaryPtr(o, r, len(bz), n, err)
} else {
wire.ReadBinary(o, r, len(bz), n, err)
}
return *err
}
func (cdc *Codec) MarshalJSON(o interface{}) ([]byte, error) {
w, n, err := new(bytes.Buffer), new(int), new(error)
wire.WriteJSON(o, w, n, err)
return w.Bytes(), *err
}
func (cdc *Codec) UnmarshalJSON(bz []byte, o interface{}) (err error) {
rv := reflect.ValueOf(o)
if rv.Kind() == reflect.Ptr {
wire.ReadJSONPtr(o, bz, &err)
} else {
wire.ReadJSON(o, bz, &err)
}
return err
}
//----------------------------------------------
func RegisterCrypto(cdc *Codec) { func RegisterCrypto(cdc *Codec) {
// TODO crypto.RegisterAmino(cdc)
}
func MarshalJSONIndent(cdc *Codec, obj interface{}) ([]byte, error) {
bz, err := cdc.MarshalJSON(obj)
if err != nil {
return nil, err
}
var out bytes.Buffer
err = json.Indent(&out, bz, "", " ")
if err != nil {
return nil, err
}
return out.Bytes(), nil
} }

View File

@ -11,7 +11,7 @@ import (
// NewAnteHandler returns an AnteHandler that checks // NewAnteHandler returns an AnteHandler that checks
// and increments sequence numbers, checks signatures, // and increments sequence numbers, checks signatures,
// and deducts fees from the first signer. // and deducts fees from the first signer.
func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler { func NewAnteHandler(accountMapper sdk.AccountMapper, feeHandler sdk.FeeHandler) sdk.AnteHandler {
return func( return func(
ctx sdk.Context, tx sdk.Tx, ctx sdk.Context, tx sdk.Tx,
) (_ sdk.Context, _ sdk.Result, abort bool) { ) (_ sdk.Context, _ sdk.Result, abort bool) {
@ -74,6 +74,7 @@ func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler {
// TODO: min fee // TODO: min fee
if !fee.Amount.IsZero() { if !fee.Amount.IsZero() {
signerAcc, res = deductFees(signerAcc, fee) signerAcc, res = deductFees(signerAcc, fee)
feeHandler(ctx, tx, fee.Amount)
if !res.IsOK() { if !res.IsOK() {
return ctx, res, true return ctx, res, true
} }
@ -118,9 +119,9 @@ func processSig(
// If pubkey is not known for account, // If pubkey is not known for account,
// set it from the StdSignature. // set it from the StdSignature.
pubKey := acc.GetPubKey() pubKey := acc.GetPubKey()
if pubKey.Empty() { if pubKey == nil {
pubKey = sig.PubKey pubKey = sig.PubKey
if pubKey.Empty() { if pubKey == nil {
return nil, sdk.ErrInvalidPubKey("PubKey not found").Result() return nil, sdk.ErrInvalidPubKey("PubKey not found").Result()
} }
if !bytes.Equal(pubKey.Address(), addr) { if !bytes.Equal(pubKey.Address(), addr) {
@ -156,3 +157,7 @@ func deductFees(acc sdk.Account, fee sdk.StdFee) (sdk.Account, sdk.Result) {
acc.SetCoins(newCoins) acc.SetCoins(newCoins)
return acc, sdk.Result{} return acc, sdk.Result{}
} }
// BurnFeeHandler burns all fees (decreasing total supply)
func BurnFeeHandler(ctx sdk.Context, tx sdk.Tx, fee sdk.Coins) {
}

View File

@ -3,11 +3,13 @@ package auth
import ( import (
"testing" "testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
abci "github.com/tendermint/abci/types" abci "github.com/tendermint/abci/types"
crypto "github.com/tendermint/go-crypto" crypto "github.com/tendermint/go-crypto"
sdk "github.com/cosmos/cosmos-sdk/types"
wire "github.com/cosmos/cosmos-sdk/wire"
) )
func newTestMsg(addrs ...sdk.Address) *sdk.TestMsg { func newTestMsg(addrs ...sdk.Address) *sdk.TestMsg {
@ -31,7 +33,7 @@ func newCoins() sdk.Coins {
func privAndAddr() (crypto.PrivKey, sdk.Address) { func privAndAddr() (crypto.PrivKey, sdk.Address) {
priv := crypto.GenPrivKeyEd25519() priv := crypto.GenPrivKeyEd25519()
addr := priv.PubKey().Address() addr := priv.PubKey().Address()
return priv.Wrap(), addr return priv, addr
} }
// run the tx through the anteHandler and ensure its valid // run the tx through the anteHandler and ensure its valid
@ -67,8 +69,10 @@ func newTestTxWithSignBytes(msg sdk.Msg, privs []crypto.PrivKey, seqs []int64, f
func TestAnteHandlerSigErrors(t *testing.T) { func TestAnteHandlerSigErrors(t *testing.T) {
// setup // setup
ms, capKey := setupMultiStore() ms, capKey := setupMultiStore()
mapper := NewAccountMapper(capKey, &BaseAccount{}) cdc := wire.NewCodec()
anteHandler := NewAnteHandler(mapper) RegisterBaseAccount(cdc)
mapper := NewAccountMapper(cdc, capKey, &BaseAccount{})
anteHandler := NewAnteHandler(mapper, BurnFeeHandler)
ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil) ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil)
// keys and addresses // keys and addresses
@ -106,8 +110,10 @@ func TestAnteHandlerSigErrors(t *testing.T) {
func TestAnteHandlerSequences(t *testing.T) { func TestAnteHandlerSequences(t *testing.T) {
// setup // setup
ms, capKey := setupMultiStore() ms, capKey := setupMultiStore()
mapper := NewAccountMapper(capKey, &BaseAccount{}) cdc := wire.NewCodec()
anteHandler := NewAnteHandler(mapper) RegisterBaseAccount(cdc)
mapper := NewAccountMapper(cdc, capKey, &BaseAccount{})
anteHandler := NewAnteHandler(mapper, BurnFeeHandler)
ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil) ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil)
// keys and addresses // keys and addresses
@ -170,8 +176,10 @@ func TestAnteHandlerSequences(t *testing.T) {
func TestAnteHandlerFees(t *testing.T) { func TestAnteHandlerFees(t *testing.T) {
// setup // setup
ms, capKey := setupMultiStore() ms, capKey := setupMultiStore()
mapper := NewAccountMapper(capKey, &BaseAccount{}) cdc := wire.NewCodec()
anteHandler := NewAnteHandler(mapper) RegisterBaseAccount(cdc)
mapper := NewAccountMapper(cdc, capKey, &BaseAccount{})
anteHandler := NewAnteHandler(mapper, BurnFeeHandler)
ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil) ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil)
// keys and addresses // keys and addresses
@ -205,8 +213,10 @@ func TestAnteHandlerFees(t *testing.T) {
func TestAnteHandlerBadSignBytes(t *testing.T) { func TestAnteHandlerBadSignBytes(t *testing.T) {
// setup // setup
ms, capKey := setupMultiStore() ms, capKey := setupMultiStore()
mapper := NewAccountMapper(capKey, &BaseAccount{}) cdc := wire.NewCodec()
anteHandler := NewAnteHandler(mapper) RegisterBaseAccount(cdc)
mapper := NewAccountMapper(cdc, capKey, &BaseAccount{})
anteHandler := NewAnteHandler(mapper, BurnFeeHandler)
ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil) ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil)
// keys and addresses // keys and addresses
@ -278,8 +288,10 @@ func TestAnteHandlerBadSignBytes(t *testing.T) {
func TestAnteHandlerSetPubKey(t *testing.T) { func TestAnteHandlerSetPubKey(t *testing.T) {
// setup // setup
ms, capKey := setupMultiStore() ms, capKey := setupMultiStore()
mapper := NewAccountMapper(capKey, &BaseAccount{}) cdc := wire.NewCodec()
anteHandler := NewAnteHandler(mapper) RegisterBaseAccount(cdc)
mapper := NewAccountMapper(cdc, capKey, &BaseAccount{})
anteHandler := NewAnteHandler(mapper, BurnFeeHandler)
ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil) ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil)
// keys and addresses // keys and addresses
@ -310,16 +322,16 @@ func TestAnteHandlerSetPubKey(t *testing.T) {
msg = newTestMsg(addr2) msg = newTestMsg(addr2)
tx = newTestTx(ctx, msg, privs, seqs, fee) tx = newTestTx(ctx, msg, privs, seqs, fee)
sigs := tx.GetSignatures() sigs := tx.GetSignatures()
sigs[0].PubKey = crypto.PubKey{} sigs[0].PubKey = nil
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidPubKey) checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidPubKey)
acc2 = mapper.GetAccount(ctx, addr2) acc2 = mapper.GetAccount(ctx, addr2)
assert.True(t, acc2.GetPubKey().Empty()) assert.Nil(t, acc2.GetPubKey())
// test invalid signature and public key // test invalid signature and public key
tx = newTestTx(ctx, msg, privs, seqs, fee) tx = newTestTx(ctx, msg, privs, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidPubKey) checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidPubKey)
acc2 = mapper.GetAccount(ctx, addr2) acc2 = mapper.GetAccount(ctx, addr2)
assert.True(t, acc2.GetPubKey().Empty()) assert.Nil(t, acc2.GetPubKey())
} }

View File

@ -61,7 +61,7 @@ func (acc BaseAccount) GetPubKey() crypto.PubKey {
// Implements sdk.Account. // Implements sdk.Account.
func (acc *BaseAccount) SetPubKey(pubKey crypto.PubKey) error { func (acc *BaseAccount) SetPubKey(pubKey crypto.PubKey) error {
if !acc.PubKey.Empty() { if acc.PubKey != nil {
return errors.New("cannot override BaseAccount pubkey") return errors.New("cannot override BaseAccount pubkey")
} }
acc.PubKey = pubKey acc.PubKey = pubKey
@ -93,7 +93,9 @@ func (acc *BaseAccount) SetSequence(seq int64) error {
//---------------------------------------- //----------------------------------------
// Wire // Wire
func RegisterWireBaseAccount(cdc *wire.Codec) { // Most users shouldn't use this, but this comes handy for tests.
// Register crypto.[PubKey,PrivKey,Signature] types. func RegisterBaseAccount(cdc *wire.Codec) {
cdc.RegisterInterface((*sdk.Account)(nil), nil)
cdc.RegisterConcrete(&BaseAccount{}, "cosmos-sdk/BaseAccount", nil)
wire.RegisterCrypto(cdc) wire.RegisterCrypto(cdc)
} }

View File

@ -15,7 +15,7 @@ func keyPubAddr() (crypto.PrivKey, crypto.PubKey, sdk.Address) {
key := crypto.GenPrivKeyEd25519() key := crypto.GenPrivKeyEd25519()
pub := key.PubKey() pub := key.PubKey()
addr := pub.Address() addr := pub.Address()
return key.Wrap(), pub, addr return key, pub, addr
} }
func TestBaseAccountAddressPubKey(t *testing.T) { func TestBaseAccountAddressPubKey(t *testing.T) {
@ -25,7 +25,7 @@ func TestBaseAccountAddressPubKey(t *testing.T) {
// check the address (set) and pubkey (not set) // check the address (set) and pubkey (not set)
assert.EqualValues(t, addr1, acc.GetAddress()) assert.EqualValues(t, addr1, acc.GetAddress())
assert.EqualValues(t, crypto.PubKey{}, acc.GetPubKey()) assert.EqualValues(t, nil, acc.GetPubKey())
// can't override address // can't override address
err := acc.SetAddress(addr2) err := acc.SetAddress(addr2)

View File

@ -2,7 +2,6 @@ package commands
import ( import (
"encoding/hex" "encoding/hex"
"encoding/json"
"fmt" "fmt"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -11,7 +10,6 @@ import (
"github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/context"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/auth"
) )
// GetAccountCmd for the auth.BaseAccount type // GetAccountCmd for the auth.BaseAccount type
@ -20,9 +18,9 @@ func GetAccountCmdDefault(storeName string, cdc *wire.Codec) *cobra.Command {
} }
func GetAccountDecoder(cdc *wire.Codec) sdk.AccountDecoder { func GetAccountDecoder(cdc *wire.Codec) sdk.AccountDecoder {
return func(accBytes []byte) (sdk.Account, error) { return func(accBytes []byte) (acct sdk.Account, err error) {
acct := new(auth.BaseAccount) // acct := new(auth.BaseAccount)
err := cdc.UnmarshalBinary(accBytes, &acct) err = cdc.UnmarshalBinaryBare(accBytes, &acct)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -78,7 +76,7 @@ func (c commander) getAccountCmd(cmd *cobra.Command, args []string) error {
} }
// print out whole account // print out whole account
output, err := json.MarshalIndent(account, "", " ") output, err := wire.MarshalJSONIndent(c.cdc, account)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,12 +1,9 @@
package auth package auth
import ( import (
"bytes"
"fmt" "fmt"
"reflect" "reflect"
oldwire "github.com/tendermint/go-wire"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
wire "github.com/cosmos/cosmos-sdk/wire" wire "github.com/cosmos/cosmos-sdk/wire"
) )
@ -16,7 +13,7 @@ var _ sdk.AccountMapper = (*sealedAccountMapper)(nil)
// Implements sdk.AccountMapper. // Implements sdk.AccountMapper.
// This AccountMapper encodes/decodes accounts using the // This AccountMapper encodes/decodes accounts using the
// go-wire (binary) encoding/decoding library. // go-amino (binary) encoding/decoding library.
type accountMapper struct { type accountMapper struct {
// The (unexposed) key used to access the store from the Context. // The (unexposed) key used to access the store from the Context.
@ -30,9 +27,8 @@ type accountMapper struct {
} }
// NewAccountMapper returns a new sdk.AccountMapper that // NewAccountMapper returns a new sdk.AccountMapper that
// uses go-wire to (binary) encode and decode concrete sdk.Accounts. // uses go-amino to (binary) encode and decode concrete sdk.Accounts.
func NewAccountMapper(key sdk.StoreKey, proto sdk.Account) accountMapper { func NewAccountMapper(cdc *wire.Codec, key sdk.StoreKey, proto sdk.Account) accountMapper {
cdc := wire.NewCodec()
return accountMapper{ return accountMapper{
key: key, key: key,
proto: proto, proto: proto,
@ -40,21 +36,7 @@ func NewAccountMapper(key sdk.StoreKey, proto sdk.Account) accountMapper {
} }
} }
// Create and return a sealed account mapper // Returns the go-amino codec. You may need to register interfaces
func NewAccountMapperSealed(key sdk.StoreKey, proto sdk.Account) sealedAccountMapper {
cdc := wire.NewCodec()
am := accountMapper{
key: key,
proto: proto,
cdc: cdc,
}
RegisterWireBaseAccount(cdc)
// make accountMapper's WireCodec() inaccessible, return
return am.Seal()
}
// Returns the go-wire codec. You may need to register interfaces
// and concrete types here, if your app's sdk.Account // and concrete types here, if your app's sdk.Account
// implementation includes interface fields. // implementation includes interface fields.
// NOTE: It is not secure to expose the codec, so check out // NOTE: It is not secure to expose the codec, so check out
@ -103,7 +85,7 @@ type sealedAccountMapper struct {
} }
// There's no way for external modules to mutate the // There's no way for external modules to mutate the
// sam.accountMapper.ctx from here, even with reflection. // sam.accountMapper.cdc from here, even with reflection.
func (sam sealedAccountMapper) WireCodec() *wire.Codec { func (sam sealedAccountMapper) WireCodec() *wire.Codec {
panic("accountMapper is sealed") panic("accountMapper is sealed")
} }
@ -111,22 +93,6 @@ func (sam sealedAccountMapper) WireCodec() *wire.Codec {
//---------------------------------------- //----------------------------------------
// misc. // misc.
// NOTE: currently unused
func (am accountMapper) clonePrototypePtr() interface{} {
protoRt := reflect.TypeOf(am.proto)
if protoRt.Kind() == reflect.Ptr {
protoErt := protoRt.Elem()
if protoErt.Kind() != reflect.Struct {
panic("accountMapper requires a struct proto sdk.Account, or a pointer to one")
}
protoRv := reflect.New(protoErt)
return protoRv.Interface()
} else {
protoRv := reflect.New(protoRt)
return protoRv.Interface()
}
}
// Creates a new struct (or pointer to struct) from am.proto. // Creates a new struct (or pointer to struct) from am.proto.
func (am accountMapper) clonePrototype() sdk.Account { func (am accountMapper) clonePrototype() sdk.Account {
protoRt := reflect.TypeOf(am.proto) protoRt := reflect.TypeOf(am.proto)
@ -152,34 +118,17 @@ func (am accountMapper) clonePrototype() sdk.Account {
} }
func (am accountMapper) encodeAccount(acc sdk.Account) []byte { func (am accountMapper) encodeAccount(acc sdk.Account) []byte {
bz, err := am.cdc.MarshalBinary(acc) bz, err := am.cdc.MarshalBinaryBare(acc)
if err != nil { if err != nil {
panic(err) panic(err)
} }
return bz return bz
} }
func (am accountMapper) decodeAccount(bz []byte) sdk.Account { func (am accountMapper) decodeAccount(bz []byte) (acc sdk.Account) {
// ... old go-wire ... err := am.cdc.UnmarshalBinaryBare(bz, &acc)
r, n, err := bytes.NewBuffer(bz), new(int), new(error)
accI := oldwire.ReadBinary(struct{ sdk.Account }{}, r, len(bz), n, err)
if *err != nil {
panic(*err)
}
acc := accI.(struct{ sdk.Account }).Account
return acc
/*
accPtr := am.clonePrototypePtr()
err := am.cdc.UnmarshalBinary(bz, accPtr)
if err != nil { if err != nil {
panic(err) panic(err)
} }
if reflect.ValueOf(am.proto).Kind() == reflect.Ptr { return
return reflect.ValueOf(accPtr).Interface().(sdk.Account)
} else {
return reflect.ValueOf(accPtr).Elem().Interface().(sdk.Account)
}
*/
} }

View File

@ -6,12 +6,11 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
abci "github.com/tendermint/abci/types" abci "github.com/tendermint/abci/types"
crypto "github.com/tendermint/go-crypto"
oldwire "github.com/tendermint/go-wire"
dbm "github.com/tendermint/tmlibs/db" dbm "github.com/tendermint/tmlibs/db"
"github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
wire "github.com/cosmos/cosmos-sdk/wire"
) )
func setupMultiStore() (sdk.MultiStore, *sdk.KVStoreKey) { func setupMultiStore() (sdk.MultiStore, *sdk.KVStoreKey) {
@ -20,22 +19,17 @@ func setupMultiStore() (sdk.MultiStore, *sdk.KVStoreKey) {
ms := store.NewCommitMultiStore(db) ms := store.NewCommitMultiStore(db)
ms.MountStoreWithDB(capKey, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(capKey, sdk.StoreTypeIAVL, db)
ms.LoadLatestVersion() ms.LoadLatestVersion()
// wire registration while we're at it ... TODO
var _ = oldwire.RegisterInterface(
struct{ sdk.Account }{},
oldwire.ConcreteType{&BaseAccount{}, 0x1},
)
return ms, capKey return ms, capKey
} }
func TestAccountMapperGetSet(t *testing.T) { func TestAccountMapperGetSet(t *testing.T) {
ms, capKey := setupMultiStore() ms, capKey := setupMultiStore()
cdc := wire.NewCodec()
RegisterBaseAccount(cdc)
// make context and mapper // make context and mapper
ctx := sdk.NewContext(ms, abci.Header{}, false, nil) ctx := sdk.NewContext(ms, abci.Header{}, false, nil)
mapper := NewAccountMapper(capKey, &BaseAccount{}) mapper := NewAccountMapper(cdc, capKey, &BaseAccount{})
addr := sdk.Address([]byte("some-address")) addr := sdk.Address([]byte("some-address"))
@ -47,7 +41,7 @@ func TestAccountMapperGetSet(t *testing.T) {
acc = mapper.NewAccountWithAddress(ctx, addr) acc = mapper.NewAccountWithAddress(ctx, addr)
assert.NotNil(t, acc) assert.NotNil(t, acc)
assert.Equal(t, addr, acc.GetAddress()) assert.Equal(t, addr, acc.GetAddress())
assert.EqualValues(t, crypto.PubKey{}, acc.GetPubKey()) assert.EqualValues(t, nil, acc.GetPubKey())
assert.EqualValues(t, 0, acc.GetSequence()) assert.EqualValues(t, 0, acc.GetSequence())
// NewAccount doesn't call Set, so it's still nil // NewAccount doesn't call Set, so it's still nil
@ -66,16 +60,14 @@ func TestAccountMapperGetSet(t *testing.T) {
func TestAccountMapperSealed(t *testing.T) { func TestAccountMapperSealed(t *testing.T) {
_, capKey := setupMultiStore() _, capKey := setupMultiStore()
cdc := wire.NewCodec()
RegisterBaseAccount(cdc)
// normal mapper exposes the wire codec // normal mapper exposes the wire codec
mapper := NewAccountMapper(capKey, &BaseAccount{}) mapper := NewAccountMapper(cdc, capKey, &BaseAccount{})
assert.NotNil(t, mapper.WireCodec()) assert.NotNil(t, mapper.WireCodec())
// seal mapper, should panic when we try to get the codec // seal mapper, should panic when we try to get the codec
mapperSealed := mapper.Seal() mapperSealed := mapper.Seal()
assert.Panics(t, func() { mapperSealed.WireCodec() }) assert.Panics(t, func() { mapperSealed.WireCodec() })
// another way to get a sealed mapper
mapperSealed = NewAccountMapperSealed(capKey, &BaseAccount{})
assert.Panics(t, func() { mapperSealed.WireCodec() })
} }

View File

@ -2,7 +2,6 @@ package rest
import ( import (
"encoding/hex" "encoding/hex"
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
@ -56,7 +55,7 @@ func QueryAccountRequestHandler(storeName string, cdc *wire.Codec, decoder sdk.A
} }
// print out whole account // print out whole account
output, err := json.MarshalIndent(account, "", " ") output, err := cdc.MarshalJSON(account)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("Could't marshall query result. Error: %s", err.Error()))) w.Write([]byte(fmt.Sprintf("Could't marshall query result. Error: %s", err.Error())))

View File

@ -7,12 +7,11 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/context"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/wire"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands"
"github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/bank"
cryptokeys "github.com/tendermint/go-crypto/keys"
) )
const ( const (
@ -38,7 +37,7 @@ type Commander struct {
} }
func (c Commander) sendTxCmd(cmd *cobra.Command, args []string) error { func (c Commander) sendTxCmd(cmd *cobra.Command, args []string) error {
ctx := context.NewCoreContextFromViper() ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(c.Cdc))
// get the from address // get the from address
from, err := ctx.GetFromAddress() from, err := ctx.GetFromAddress()
@ -64,6 +63,12 @@ func (c Commander) sendTxCmd(cmd *cobra.Command, args []string) error {
// build message // build message
msg := BuildMsg(from, to, coins) msg := BuildMsg(from, to, coins)
// default to next sequence number if none provided
ctx, err = context.EnsureSequence(ctx)
if err != nil {
return err
}
// build and sign the transaction, then broadcast to Tendermint // build and sign the transaction, then broadcast to Tendermint
res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, c.Cdc) res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, c.Cdc)
if err != nil { if err != nil {
@ -80,29 +85,3 @@ func BuildMsg(from sdk.Address, to sdk.Address, coins sdk.Coins) sdk.Msg {
msg := bank.NewSendMsg([]bank.Input{input}, []bank.Output{output}) msg := bank.NewSendMsg([]bank.Input{input}, []bank.Output{output})
return msg return msg
} }
func (c Commander) SignMessage(msg sdk.Msg, kb cryptokeys.Keybase, accountName string, password string) ([]byte, error) {
// sign and build
bz := msg.GetSignBytes()
sig, pubkey, err := kb.Sign(accountName, password, bz)
if err != nil {
return nil, err
}
sigs := []sdk.StdSignature{{
PubKey: pubkey,
Signature: sig,
Sequence: viper.GetInt64(client.FlagName),
}}
// TODO: fees
var fee sdk.StdFee
// marshal bytes
tx := sdk.NewStdTx(msg, fee, sigs)
txBytes, err := c.Cdc.MarshalBinary(tx)
if err != nil {
return nil, err
}
return txBytes, nil
}

View File

@ -13,6 +13,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
wire "github.com/cosmos/cosmos-sdk/wire" wire "github.com/cosmos/cosmos-sdk/wire"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands"
"github.com/cosmos/cosmos-sdk/x/ibc" "github.com/cosmos/cosmos-sdk/x/ibc"
) )
@ -39,7 +40,7 @@ type sendCommander struct {
} }
func (c sendCommander) sendIBCTransfer(cmd *cobra.Command, args []string) error { func (c sendCommander) sendIBCTransfer(cmd *cobra.Command, args []string) error {
ctx := context.NewCoreContextFromViper() ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(c.cdc))
// get the from address // get the from address
from, err := ctx.GetFromAddress() from, err := ctx.GetFromAddress()
@ -53,6 +54,12 @@ func (c sendCommander) sendIBCTransfer(cmd *cobra.Command, args []string) error
return err return err
} }
// default to next sequence number if none provided
ctx, err = context.EnsureSequence(ctx)
if err != nil {
return err
}
// get password // get password
res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, c.cdc) res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, c.cdc)
if err != nil { if err != nil {

View File

@ -7,7 +7,6 @@ import (
abci "github.com/tendermint/abci/types" abci "github.com/tendermint/abci/types"
"github.com/tendermint/go-crypto" "github.com/tendermint/go-crypto"
oldwire "github.com/tendermint/go-wire"
dbm "github.com/tendermint/tmlibs/db" dbm "github.com/tendermint/tmlibs/db"
"github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/store"
@ -33,39 +32,25 @@ func newAddress() crypto.Address {
} }
func getCoins(ck bank.CoinKeeper, ctx sdk.Context, addr crypto.Address) (sdk.Coins, sdk.Error) { func getCoins(ck bank.CoinKeeper, ctx sdk.Context, addr crypto.Address) (sdk.Coins, sdk.Error) {
zero := sdk.Coins{} zero := sdk.Coins(nil)
return ck.AddCoins(ctx, addr, zero) return ck.AddCoins(ctx, addr, zero)
} }
// custom tx codec
// TODO: use new go-wire
func makeCodec() *wire.Codec { func makeCodec() *wire.Codec {
var cdc = wire.NewCodec()
const msgTypeSend = 0x1 // Register Msgs
const msgTypeIssue = 0x2 cdc.RegisterInterface((*sdk.Msg)(nil), nil)
const msgTypeQuiz = 0x3 cdc.RegisterConcrete(bank.SendMsg{}, "test/ibc/Send", nil)
const msgTypeSetTrend = 0x4 cdc.RegisterConcrete(bank.IssueMsg{}, "test/ibc/Issue", nil)
const msgTypeIBCTransferMsg = 0x5 cdc.RegisterConcrete(IBCTransferMsg{}, "test/ibc/IBCTransferMsg", nil)
const msgTypeIBCReceiveMsg = 0x6 cdc.RegisterConcrete(IBCReceiveMsg{}, "test/ibc/IBCReceiveMsg", nil)
var _ = oldwire.RegisterInterface(
struct{ sdk.Msg }{},
oldwire.ConcreteType{bank.SendMsg{}, msgTypeSend},
oldwire.ConcreteType{bank.IssueMsg{}, msgTypeIssue},
oldwire.ConcreteType{IBCTransferMsg{}, msgTypeIBCTransferMsg},
oldwire.ConcreteType{IBCReceiveMsg{}, msgTypeIBCReceiveMsg},
)
const accTypeApp = 0x1 // Register AppAccount
var _ = oldwire.RegisterInterface( cdc.RegisterInterface((*sdk.Account)(nil), nil)
struct{ sdk.Account }{}, cdc.RegisterConcrete(&auth.BaseAccount{}, "test/ibc/Account", nil)
oldwire.ConcreteType{&auth.BaseAccount{}, accTypeApp}, wire.RegisterCrypto(cdc)
)
cdc := wire.NewCodec()
// cdc.RegisterInterface((*sdk.Msg)(nil), nil)
// bank.RegisterWire(cdc) // Register bank.[SendMsg,IssueMsg] types.
// crypto.RegisterWire(cdc) // Register crypto.[PubKey,PrivKey,Signature] types.
// ibc.RegisterWire(cdc) // Register ibc.[IBCTransferMsg, IBCReceiveMsg] types.
return cdc return cdc
} }
@ -75,13 +60,13 @@ func TestIBC(t *testing.T) {
key := sdk.NewKVStoreKey("ibc") key := sdk.NewKVStoreKey("ibc")
ctx := defaultContext(key) ctx := defaultContext(key)
am := auth.NewAccountMapper(key, &auth.BaseAccount{}) am := auth.NewAccountMapper(cdc, key, &auth.BaseAccount{})
ck := bank.NewCoinKeeper(am) ck := bank.NewCoinKeeper(am)
src := newAddress() src := newAddress()
dest := newAddress() dest := newAddress()
chainid := "ibcchain" chainid := "ibcchain"
zero := sdk.Coins{} zero := sdk.Coins(nil)
mycoins := sdk.Coins{sdk.Coin{"mycoin", 10}} mycoins := sdk.Coins{sdk.Coin{"mycoin", 10}}
coins, err := ck.AddCoins(ctx, src, mycoins) coins, err := ck.AddCoins(ctx, src, mycoins)

View File

@ -2,7 +2,6 @@ package rest
import ( import (
"encoding/hex" "encoding/hex"
"encoding/json"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
@ -43,7 +42,7 @@ func TransferRequestHandler(cdc *wire.Codec, kb keys.Keybase) func(http.Response
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
} }
err = json.Unmarshal(body, &m) err = cdc.UnmarshalJSON(body, &m)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
@ -86,7 +85,7 @@ func TransferRequestHandler(cdc *wire.Codec, kb keys.Keybase) func(http.Response
return return
} }
output, err := json.MarshalIndent(res, "", " ") output, err := cdc.MarshalJSON(res)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))

View File

@ -12,6 +12,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/context"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/wire"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands"
"github.com/cosmos/cosmos-sdk/x/simplestake" "github.com/cosmos/cosmos-sdk/x/simplestake"
) )
@ -77,7 +78,7 @@ func (co commander) bondTxCmd(cmd *cobra.Command, args []string) error {
var pubKeyEd crypto.PubKeyEd25519 var pubKeyEd crypto.PubKeyEd25519
copy(pubKeyEd[:], rawPubKey) copy(pubKeyEd[:], rawPubKey)
msg := simplestake.NewBondMsg(from, stake, pubKeyEd.Wrap()) msg := simplestake.NewBondMsg(from, stake, pubKeyEd)
return co.sendMsg(msg) return co.sendMsg(msg)
} }
@ -94,7 +95,14 @@ func (co commander) unbondTxCmd(cmd *cobra.Command, args []string) error {
} }
func (co commander) sendMsg(msg sdk.Msg) error { func (co commander) sendMsg(msg sdk.Msg) error {
ctx := context.NewCoreContextFromViper() ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(co.cdc))
// default to next sequence number if none provided
ctx, err := context.EnsureSequence(ctx)
if err != nil {
return err
}
res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, co.cdc) res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, co.cdc)
if err != nil { if err != nil {
return err return err

View File

@ -21,6 +21,7 @@ type Keeper struct {
func NewKeeper(key sdk.StoreKey, coinKeeper bank.CoinKeeper) Keeper { func NewKeeper(key sdk.StoreKey, coinKeeper bank.CoinKeeper) Keeper {
cdc := wire.NewCodec() cdc := wire.NewCodec()
wire.RegisterCrypto(cdc)
return Keeper{ return Keeper{
key: key, key: key,
cdc: cdc, cdc: cdc,
@ -83,7 +84,7 @@ func (k Keeper) Bond(ctx sdk.Context, addr sdk.Address, pubKey crypto.PubKey, st
func (k Keeper) Unbond(ctx sdk.Context, addr sdk.Address) (crypto.PubKey, int64, sdk.Error) { func (k Keeper) Unbond(ctx sdk.Context, addr sdk.Address) (crypto.PubKey, int64, sdk.Error) {
bi := k.getBondInfo(ctx, addr) bi := k.getBondInfo(ctx, addr)
if bi.isEmpty() { if bi.isEmpty() {
return crypto.PubKey{}, 0, ErrInvalidUnbond() return nil, 0, ErrInvalidUnbond()
} }
k.deleteBondInfo(ctx, addr) k.deleteBondInfo(ctx, addr)
@ -121,7 +122,7 @@ func (k Keeper) bondWithoutCoins(ctx sdk.Context, addr sdk.Address, pubKey crypt
func (k Keeper) unbondWithoutCoins(ctx sdk.Context, addr sdk.Address) (crypto.PubKey, int64, sdk.Error) { func (k Keeper) unbondWithoutCoins(ctx sdk.Context, addr sdk.Address) (crypto.PubKey, int64, sdk.Error) {
bi := k.getBondInfo(ctx, addr) bi := k.getBondInfo(ctx, addr)
if bi.isEmpty() { if bi.isEmpty() {
return crypto.PubKey{}, 0, ErrInvalidUnbond() return nil, 0, ErrInvalidUnbond()
} }
k.deleteBondInfo(ctx, addr) k.deleteBondInfo(ctx, addr)

View File

@ -13,6 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/bank"
) )
@ -55,10 +56,12 @@ func TestKeeperGetSet(t *testing.T) {
func TestBonding(t *testing.T) { func TestBonding(t *testing.T) {
ms, authKey, capKey := setupMultiStore() ms, authKey, capKey := setupMultiStore()
cdc := wire.NewCodec()
auth.RegisterBaseAccount(cdc)
ctx := sdk.NewContext(ms, abci.Header{}, false, nil) ctx := sdk.NewContext(ms, abci.Header{}, false, nil)
accountMapper := auth.NewAccountMapper(authKey, &auth.BaseAccount{}) accountMapper := auth.NewAccountMapper(cdc, authKey, &auth.BaseAccount{})
coinKeeper := bank.NewCoinKeeper(accountMapper) coinKeeper := bank.NewCoinKeeper(accountMapper)
stakeKeeper := NewKeeper(capKey, coinKeeper) stakeKeeper := NewKeeper(capKey, coinKeeper)
addr := sdk.Address([]byte("some-address")) addr := sdk.Address([]byte("some-address"))

View File

@ -34,7 +34,7 @@ func (msg BondMsg) ValidateBasic() sdk.Error {
return ErrEmptyStake() return ErrEmptyStake()
} }
if msg.PubKey.Empty() { if msg.PubKey == nil {
return sdk.ErrInvalidPubKey("BondMsg.PubKey must not be empty") return sdk.ErrInvalidPubKey("BondMsg.PubKey must not be empty")
} }

View File

@ -2,7 +2,6 @@ package commands
import ( import (
"encoding/hex" "encoding/hex"
"encoding/json"
"fmt" "fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -59,7 +58,7 @@ func GetCmdQueryCandidates(cdc *wire.Codec, storeName string) *cobra.Command {
if err != nil { if err != nil {
return err return err
} }
output, err := json.MarshalIndent(candidates, "", " ") output, err := wire.MarshalJSONIndent(cdc, candidates)
if err != nil { if err != nil {
return err return err
} }
@ -101,7 +100,7 @@ func GetCmdQueryCandidate(cdc *wire.Codec, storeName string) *cobra.Command {
if err != nil { if err != nil {
return err return err
} }
output, err := json.MarshalIndent(candidate, "", " ") output, err := wire.MarshalJSONIndent(cdc, candidate)
if err != nil { if err != nil {
return err return err
} }
@ -149,7 +148,7 @@ func GetCmdQueryDelegatorBond(cdc *wire.Codec, storeName string) *cobra.Command
if err != nil { if err != nil {
return err return err
} }
output, err := json.MarshalIndent(bond, "", " ") output, err := wire.MarshalJSONIndent(cdc, bond)
if err != nil { if err != nil {
return err return err
} }
@ -193,7 +192,7 @@ func GetCmdQueryDelegatorBonds(cdc *wire.Codec, storeName string) *cobra.Command
if err != nil { if err != nil {
return err return err
} }
output, err := json.MarshalIndent(candidates, "", " ") output, err := wire.MarshalJSONIndent(cdc, candidates)
if err != nil { if err != nil {
return err return err
} }

View File

@ -14,6 +14,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/context"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/wire"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands"
"github.com/cosmos/cosmos-sdk/x/stake" "github.com/cosmos/cosmos-sdk/x/stake"
) )
@ -92,7 +93,14 @@ func GetCmdDeclareCandidacy(cdc *wire.Codec) *cobra.Command {
msg := stake.NewMsgDeclareCandidacy(candidateAddr, pk, amount, description) msg := stake.NewMsgDeclareCandidacy(candidateAddr, pk, amount, description)
// build and sign the transaction, then broadcast to Tendermint // build and sign the transaction, then broadcast to Tendermint
ctx := context.NewCoreContextFromViper() ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
// default to next sequence number if none provided
ctx, err = context.EnsureSequence(ctx)
if err != nil {
return err
}
res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc) res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc)
if err != nil { if err != nil {
return err return err
@ -129,7 +137,14 @@ func GetCmdEditCandidacy(cdc *wire.Codec) *cobra.Command {
msg := stake.NewMsgEditCandidacy(candidateAddr, description) msg := stake.NewMsgEditCandidacy(candidateAddr, description)
// build and sign the transaction, then broadcast to Tendermint // build and sign the transaction, then broadcast to Tendermint
ctx := context.NewCoreContextFromViper() ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
// default to next sequence number if none provided
ctx, err = context.EnsureSequence(ctx)
if err != nil {
return err
}
res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc) res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc)
if err != nil { if err != nil {
return err return err
@ -165,7 +180,14 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command {
msg := stake.NewMsgDelegate(delegatorAddr, candidateAddr, amount) msg := stake.NewMsgDelegate(delegatorAddr, candidateAddr, amount)
// build and sign the transaction, then broadcast to Tendermint // build and sign the transaction, then broadcast to Tendermint
ctx := context.NewCoreContextFromViper() ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
// default to next sequence number if none provided
ctx, err = context.EnsureSequence(ctx)
if err != nil {
return err
}
res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc) res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc)
if err != nil { if err != nil {
return err return err
@ -212,7 +234,14 @@ func GetCmdUnbond(cdc *wire.Codec) *cobra.Command {
msg := stake.NewMsgUnbond(delegatorAddr, candidateAddr, sharesStr) msg := stake.NewMsgUnbond(delegatorAddr, candidateAddr, sharesStr)
// build and sign the transaction, then broadcast to Tendermint // build and sign the transaction, then broadcast to Tendermint
ctx := context.NewCoreContextFromViper() ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
// default to next sequence number if none provided
ctx, err = context.EnsureSequence(ctx)
if err != nil {
return err
}
res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc) res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc)
if err != nil { if err != nil {
return err return err
@ -250,6 +279,6 @@ func GetPubKey(pubKeyStr string) (pk crypto.PubKey, err error) {
} }
var pkEd crypto.PubKeyEd25519 var pkEd crypto.PubKeyEd25519
copy(pkEd[:], pkBytes[:]) copy(pkEd[:], pkBytes[:])
pk = pkEd.Wrap() pk = pkEd
return return
} }

View File

@ -8,7 +8,6 @@ import (
abci "github.com/tendermint/abci/types" abci "github.com/tendermint/abci/types"
crypto "github.com/tendermint/go-crypto" crypto "github.com/tendermint/go-crypto"
oldwire "github.com/tendermint/go-wire"
dbm "github.com/tendermint/tmlibs/db" dbm "github.com/tendermint/tmlibs/db"
"github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/store"
@ -84,36 +83,22 @@ func subspace(prefix []byte) (start, end []byte) {
return prefix, end return prefix, end
} }
// custom tx codec
// TODO: use new go-wire
func makeTestCodec() *wire.Codec { func makeTestCodec() *wire.Codec {
var cdc = wire.NewCodec()
const msgTypeSend = 0x1 // Register Msgs
const msgTypeIssue = 0x2 cdc.RegisterInterface((*sdk.Msg)(nil), nil)
const msgTypeDeclareCandidacy = 0x3 cdc.RegisterConcrete(bank.SendMsg{}, "test/stake/Send", nil)
const msgTypeEditCandidacy = 0x4 cdc.RegisterConcrete(bank.IssueMsg{}, "test/stake/Issue", nil)
const msgTypeDelegate = 0x5 cdc.RegisterConcrete(MsgDeclareCandidacy{}, "test/stake/DeclareCandidacy", nil)
const msgTypeUnbond = 0x6 cdc.RegisterConcrete(MsgEditCandidacy{}, "test/stake/EditCandidacy", nil)
var _ = oldwire.RegisterInterface( cdc.RegisterConcrete(MsgUnbond{}, "test/stake/Unbond", nil)
struct{ sdk.Msg }{},
oldwire.ConcreteType{bank.SendMsg{}, msgTypeSend},
oldwire.ConcreteType{bank.IssueMsg{}, msgTypeIssue},
oldwire.ConcreteType{MsgDeclareCandidacy{}, msgTypeDeclareCandidacy},
oldwire.ConcreteType{MsgEditCandidacy{}, msgTypeEditCandidacy},
oldwire.ConcreteType{MsgDelegate{}, msgTypeDelegate},
oldwire.ConcreteType{MsgUnbond{}, msgTypeUnbond},
)
const accTypeApp = 0x1 // Register AppAccount
var _ = oldwire.RegisterInterface( cdc.RegisterInterface((*sdk.Account)(nil), nil)
struct{ sdk.Account }{}, cdc.RegisterConcrete(&auth.BaseAccount{}, "test/stake/Account", nil)
oldwire.ConcreteType{&auth.BaseAccount{}, accTypeApp}, wire.RegisterCrypto(cdc)
)
cdc := wire.NewCodec()
// cdc.RegisterInterface((*sdk.Msg)(nil), nil)
// bank.RegisterWire(cdc) // Register bank.[SendMsg,IssueMsg] types.
// crypto.RegisterWire(cdc) // Register crypto.[PubKey,PrivKey,Signature] types.
return cdc return cdc
} }
@ -141,10 +126,11 @@ func createTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context
ctx := sdk.NewContext(ms, abci.Header{ChainID: "foochainid"}, isCheckTx, nil) ctx := sdk.NewContext(ms, abci.Header{ChainID: "foochainid"}, isCheckTx, nil)
cdc := makeTestCodec() cdc := makeTestCodec()
accountMapper := auth.NewAccountMapperSealed( accountMapper := auth.NewAccountMapper(
cdc, // amino codec
keyMain, // target store keyMain, // target store
&auth.BaseAccount{}, // prototype &auth.BaseAccount{}, // prototype
) ).Seal()
ck := bank.NewCoinKeeper(accountMapper) ck := bank.NewCoinKeeper(accountMapper)
keeper := NewKeeper(ctx, cdc, keyStake, ck) keeper := NewKeeper(ctx, cdc, keyStake, ck)
keeper.setPool(ctx, initialPool()) keeper.setPool(ctx, initialPool())
@ -168,7 +154,7 @@ func newPubKey(pk string) (res crypto.PubKey) {
//res, err = crypto.PubKeyFromBytes(pkBytes) //res, err = crypto.PubKeyFromBytes(pkBytes)
var pkEd crypto.PubKeyEd25519 var pkEd crypto.PubKeyEd25519
copy(pkEd[:], pkBytes[:]) copy(pkEd[:], pkBytes[:])
return pkEd.Wrap() return pkEd
} }
// for incode address generation // for incode address generation