commit
07842b6876
|
@ -0,0 +1,5 @@
|
||||||
|
Dockerfile
|
||||||
|
Vagrantfile
|
||||||
|
|
||||||
|
build/
|
||||||
|
coverage.txt
|
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -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
|
||||||
|
|
46
Dockerfile
46
Dockerfile
|
@ -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"]
|
||||||
|
|
|
@ -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
|
||||||
|
|
15
Gopkg.toml
15
Gopkg.toml
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()))
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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"}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"`
|
||||||
|
|
|
@ -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])
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
|
@ -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)}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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}}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 = ""
|
||||||
|
|
63
wire/wire.go
63
wire/wire.go
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
}
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() })
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())))
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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"))
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue