From 890fadc8c3f44f5433c99cfa70680626f5990b42 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 13 Feb 2018 13:36:08 +0000 Subject: [PATCH 01/14] wip refactor examples/basecoin --- baseapp/genesis.go | 21 +++ examples/basecoin/Makefile | 26 +--- examples/basecoin/app/app.go | 19 +-- examples/basecoin/app/init_baseapp.go | 1 + examples/basecoin/tools/.gitignore | 1 - examples/basecoin/tools/Makefile | 62 --------- examples/basecoin/tools/glide.lock | 18 --- examples/basecoin/tools/glide.yaml | 6 - .../basecoin/tools/go-vendorinstall/main.go | 129 ------------------ examples/basecoin/tools/main.go | 12 -- examples/basecoin/types/account.go | 55 ++++++-- 11 files changed, 76 insertions(+), 274 deletions(-) delete mode 100644 examples/basecoin/tools/.gitignore delete mode 100644 examples/basecoin/tools/Makefile delete mode 100644 examples/basecoin/tools/glide.lock delete mode 100644 examples/basecoin/tools/glide.yaml delete mode 100644 examples/basecoin/tools/go-vendorinstall/main.go delete mode 100644 examples/basecoin/tools/main.go diff --git a/baseapp/genesis.go b/baseapp/genesis.go index b2dad3e33..2baff9e51 100644 --- a/baseapp/genesis.go +++ b/baseapp/genesis.go @@ -30,3 +30,24 @@ func GenesisDocFromFile(genDocFile string) (*GenesisDoc, error) { } return &genDoc, nil } + +// read app state from the genesis file +//func GenesisAppState(genesisFile string) (state json.RawMessage, err error) { +//if genesisFile == "" { +//return +//} +//jsonBlob, err := ioutil.ReadFile(genesisFile) +//if err != nil { +//return nil, err +//} +//data := make(map[string]interface{}) +//err = json.Unmarshal(jsonBlob, &data) +//if err != nil { +//return nil, err +//} +//state, ok := data["app_state"].(json.RawMessage) +//if !ok { +//return nil, errors.New("app state genesis parse error") +//} +//return state, nil +//} diff --git a/examples/basecoin/Makefile b/examples/basecoin/Makefile index aa45d0d83..c617692a5 100644 --- a/examples/basecoin/Makefile +++ b/examples/basecoin/Makefile @@ -1,41 +1,19 @@ PACKAGES=$(shell go list ./... | grep -v '/vendor/') BUILD_FLAGS = -ldflags "-X github.com/cosmos/cosmos-sdk/examples/basecoin/version.GitCommit=`git rev-parse --short HEAD`" -all: check_tools get_vendor_deps build test - -######################################## -### Build +all: get_vendor_deps build test build: go build $(BUILD_FLAGS) -o build/basecoin ./cmd/... - -######################################## -### Tools & dependencies - -check_tools: - cd tools && $(MAKE) check - -get_tools: - cd tools && $(MAKE) - get_vendor_deps: @rm -rf vendor/ - @echo "--> Running glide install" @glide install - -######################################## -### Testing - test: @go test $(PACKAGES) benchmark: @go test -bench=. $(PACKAGES) - -# To avoid unintended conflicts with file names, always add to .PHONY -# unless there is a reason not to. -# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html -.PHONY: build check_tools get_tools get_vendor_deps test benchmark +.PHONY: build get_vendor_deps test benchmark diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index 4f26d4944..a7d27c580 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -2,7 +2,6 @@ package app import ( "fmt" - "os" bam "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" @@ -15,22 +14,20 @@ import ( const appName = "BasecoinApp" -// BasecoinApp - extended ABCI application +// Extended ABCI application type BasecoinApp struct { *bam.BaseApp - router bam.Router - cdc *wire.Codec - multiStore sdk.CommitMultiStore //TODO distinguish this store from *bam.BaseApp.cms <- is this one master?? confused + router bam.Router + cdc *wire.Codec - // The key to access the substores. + // keys to access the substores capKeyMainStore *sdk.KVStoreKey capKeyIBCStore *sdk.KVStoreKey - // Object mappers: + // object mappers accountMapper sdk.AccountMapper } -// NewBasecoinApp - create new BasecoinApp // TODO: This should take in more configuration options. // TODO: This should be moved into baseapp to isolate complexity func NewBasecoinApp(genesisPath string) *BasecoinApp { @@ -73,8 +70,7 @@ func (app *BasecoinApp) RunForever() { // Start the ABCI server srv, err := server.NewServer("0.0.0.0:46658", "socket", app) if err != nil { - fmt.Println(err) - os.Exit(1) + cmn.Exit(err.Error()) } srv.Start() @@ -89,7 +85,6 @@ func (app *BasecoinApp) RunForever() { // Load the stores func (app *BasecoinApp) loadStores() { if err := app.LoadLatestVersion(app.capKeyMainStore); err != nil { - fmt.Println(err) - os.Exit(1) + cmn.Exit(err.Error()) } } diff --git a/examples/basecoin/app/init_baseapp.go b/examples/basecoin/app/init_baseapp.go index c1fcb94c6..4ab701a9f 100644 --- a/examples/basecoin/app/init_baseapp.go +++ b/examples/basecoin/app/init_baseapp.go @@ -61,6 +61,7 @@ func (app *BasecoinApp) initBaseAppInitStater() { //----------------------------------------------------- +// State to Unmarshal type GenesisState struct { Accounts []*GenesisAccount `accounts` } diff --git a/examples/basecoin/tools/.gitignore b/examples/basecoin/tools/.gitignore deleted file mode 100644 index 36f971e32..000000000 --- a/examples/basecoin/tools/.gitignore +++ /dev/null @@ -1 +0,0 @@ -bin/* diff --git a/examples/basecoin/tools/Makefile b/examples/basecoin/tools/Makefile deleted file mode 100644 index e945888ac..000000000 --- a/examples/basecoin/tools/Makefile +++ /dev/null @@ -1,62 +0,0 @@ -all: install_glide check get_vendor_deps install - - -######################################## -### Glide - -GLIDE = github.com/tendermint/glide -GLIDE_CHECK := $(shell command -v glide 2> /dev/null) - -check: -ifndef GLIDE_CHECK - @echo "No glide in path. Install with 'make install_glide'." -else - @echo "Found glide in path." -endif - -install_glide: -ifdef GLIDE_CHECK - @echo "Glide is already installed. Run 'make update_glide' to update." -else - @echo "$(ansi_grn)Installing glide$(ansi_end)" - go get -v $(GLIDE) -endif - -update_glide: - @echo "$(ansi_grn)Updating glide$(ansi_end)" - go get -u -v $(GLIDE) - - -######################################## -### Install tools - - -get_vendor_deps: check - @rm -rf vendor/ - @echo "--> Running glide install" - @glide install - -install: get_vendor_deps - @echo "$(ansi_grn)Installing tools$(ansi_end)" - @echo "$(ansi_yel)Install go-vendorinstall$(ansi_end)" - go build -o bin/go-vendorinstall go-vendorinstall/*.go - - @echo "$(ansi_yel)Install gometalinter.v2$(ansi_end)" - GOBIN=$(CURDIR)/bin ./bin/go-vendorinstall gopkg.in/alecthomas/gometalinter.v2 - - @echo "$(ansi_grn)Done installing tools$(ansi_end)" - - -######################################## -# ANSI colors - -ansi_red=\033[0;31m -ansi_grn=\033[0;32m -ansi_yel=\033[0;33m -ansi_end=\033[0m - - -# To avoid unintended conflicts with file names, always add to .PHONY -# unless there is a reason not to. -# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html -.PHONY: check install_glide update_glide get_vendor_deps install diff --git a/examples/basecoin/tools/glide.lock b/examples/basecoin/tools/glide.lock deleted file mode 100644 index db718da50..000000000 --- a/examples/basecoin/tools/glide.lock +++ /dev/null @@ -1,18 +0,0 @@ -hash: a163b1c4806024cfc9062db75a0abed285ec40461243e59af0e147db2c4bf0ce -updated: 2018-01-15T19:02:49.834182027-08:00 -imports: -- name: github.com/inconshreveable/mousetrap - version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 -- name: github.com/rigelrozanski/common - version: f691f115798593d783b9999b1263c2f4ffecc439 -- name: github.com/rigelrozanski/shelldown - version: 2e18b6eb9bf428aa524e71433296e0b7c73ae0a3 - subpackages: - - cmd/shelldown -- name: github.com/spf13/cobra - version: 7b2c5ac9fc04fc5efafb60700713d4fa609b777b -- name: github.com/spf13/pflag - version: 97afa5e7ca8a08a383cb259e06636b5e2cc7897f -- name: gopkg.in/alecthomas/gometalinter.v2 - version: 88d47c66988c5a5cb3945925da47c883800a94df -testImports: [] diff --git a/examples/basecoin/tools/glide.yaml b/examples/basecoin/tools/glide.yaml deleted file mode 100644 index 3a3e85d6a..000000000 --- a/examples/basecoin/tools/glide.yaml +++ /dev/null @@ -1,6 +0,0 @@ -package: github.com/cosmos/cosmos-sdk/tools -import: -- package: github.com/rigelrozanski/shelldown - subpackages: - - cmd/shelldown -- package: gopkg.in/alecthomas/gometalinter.v2 diff --git a/examples/basecoin/tools/go-vendorinstall/main.go b/examples/basecoin/tools/go-vendorinstall/main.go deleted file mode 100644 index c42e678f2..000000000 --- a/examples/basecoin/tools/go-vendorinstall/main.go +++ /dev/null @@ -1,129 +0,0 @@ -// https://raw.githubusercontent.com/roboll/go-vendorinstall/a3e9f0a5d5861b3bb16b93200b2c359c9846b3c5/main.go - -package main - -import ( - "errors" - "flag" - "fmt" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "strings" -) - -var ( - source = flag.String("source", "vendor", "source directory") - target = flag.String("target", "", "target directory (defaults to $GOBIN, if not set $GOPATH/bin)") - commands = flag.String("commands", "", "comma separated list of commands to execute after go install in temporary environment") - quiet = flag.Bool("quiet", false, "disable output") -) - -func main() { - flag.Parse() - - packages := flag.Args() - if len(packages) < 1 { - fail(errors.New("no packages: specify a package")) - } - - gopath, err := ioutil.TempDir("", "go-vendorinstall-gopath") - if err != nil { - fail(err) - } - print(fmt.Sprintf("gopath: %s", gopath)) - defer func() { - if err := os.RemoveAll(gopath); err != nil { - fail(err) - } - }() - - if len(*target) == 0 { - if gobin := os.Getenv("GOBIN"); len(gobin) > 0 { - target = &gobin - } else { - bin := fmt.Sprintf("%s/bin", os.Getenv("GOPATH")) - target = &bin - } - } - - gobin, err := filepath.Abs(*target) - if err != nil { - fail(err) - } - print(fmt.Sprintf("gobin: %s", gobin)) - - if err := link(gopath, *source); err != nil { - fail(err) - } - - oldpath := os.Getenv("PATH") - path := fmt.Sprintf("%s%s%s", gobin, string(os.PathListSeparator), os.Getenv("PATH")) - os.Setenv("PATH", fmt.Sprintf("%s%s%s", gobin, string(os.PathListSeparator), os.Getenv("PATH"))) - defer os.Setenv("PATH", oldpath) - - env := []string{fmt.Sprintf("PATH=%s", path), fmt.Sprintf("GOPATH=%s", gopath), fmt.Sprintf("GOBIN=%s", gobin)} - args := append([]string{"install"}, packages...) - if out, err := doexec("go", gopath, args, env); err != nil { - print(string(out)) - fail(err) - } - - if len(*commands) > 0 { - for _, cmd := range strings.Split(*commands, ",") { - split := strings.Split(cmd, " ") - if out, err := doexec(split[0], gopath, split[1:], env); err != nil { - print(string(out)) - fail(err) - } - } - } -} - -func print(msg string) { - if !*quiet { - fmt.Println(msg) - } -} - -func fail(err error) { - fmt.Printf("error: %s", err.Error()) - os.Exit(1) -} - -func link(gopath, source string) error { - srcdir, err := filepath.Abs(source) - if err != nil { - return err - } - - linkto := filepath.Join(gopath, "src") - if err := os.MkdirAll(linkto, 0777); err != nil { - return err - } - - files, err := ioutil.ReadDir(srcdir) - if err != nil { - return err - } - - for _, file := range files { - real := filepath.Join(srcdir, file.Name()) - link := filepath.Join(linkto, file.Name()) - if err := os.Symlink(real, link); err != nil { - return err - } - } - - return nil -} - -func doexec(bin, dir string, args []string, env []string) ([]byte, error) { - print(fmt.Sprintf("%s %s", bin, strings.Join(args, " "))) - cmd := exec.Command(bin, args...) - cmd.Env = env - cmd.Dir = dir - - return cmd.CombinedOutput() -} diff --git a/examples/basecoin/tools/main.go b/examples/basecoin/tools/main.go deleted file mode 100644 index 7fd61d589..000000000 --- a/examples/basecoin/tools/main.go +++ /dev/null @@ -1,12 +0,0 @@ -package main - -import ( - // Include dependencies here so glide picks them up - // and installs sub-dependencies. - - // TODO: Ideally this gets auto-imported on glide update. - // Any way to make that happen? - _ "github.com/rigelrozanski/common" -) - -func main() {} diff --git a/examples/basecoin/types/account.go b/examples/basecoin/types/account.go index 28a1f4155..4316adc6f 100644 --- a/examples/basecoin/types/account.go +++ b/examples/basecoin/types/account.go @@ -3,25 +3,60 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" + crypto "github.com/tendermint/go-crypto" ) var _ sdk.Account = (*AppAccount)(nil) +// Custom extensions for this application. This is just an example of +// extending auth.BaseAccount with custom fields. +// +// This is compatible with the stock auth.AccountStore, since +// auth.AccountStore uses the flexible go-wire library. type AppAccount struct { auth.BaseAccount - - // Custom extensions for this application. This is just an example of - // extending auth.BaseAccount with custom fields. - // - // This is compatible with the stock auth.AccountStore, since - // auth.AccountStore uses the flexible go-wire library. Name string } -func (acc AppAccount) GetName() string { - return acc.Name +// nolint +func (acc AppAccount) GetName() string { return acc.Name } +func (acc *AppAccount) SetName(name string) { acc.Name = name } + +//___________________________________________________________________________________ + +// We use GenesisAccount instead of AppAccount for cleaner json input of PubKey +type GenesisAccount struct { + Name string `json:"name"` + Address crypto.Address `json:"address"` + Coins sdk.Coins `json:"coins"` + PubKey cmn.HexBytes `json:"public_key"` + Sequence int64 `json:"sequence"` } -func (acc *AppAccount) SetName(name string) { - acc.Name = name +func NewGenesisAccount(aa *AppAccount) *GenesisAccount { + return &GenesisAccount{ + Name: aa.Name, + Address: aa.Address, + Coins: aa.Coins, + PubKey: aa.PubKey.Bytes(), + Sequence: aa.Sequence, + } +} + +// convert GenesisAccount to AppAccount +func (ga *GenesisAccount) toAppAccount() (acc *AppAccount, err error) { + pk, err := crypto.PubKeyFromBytes(ga.PubKey) + if err != nil { + return + } + baseAcc := auth.BaseAccount{ + Address: ga.Address, + Coins: ga.Coins, + PubKey: pk, + Sequence: ga.Sequence, + } + return &AppAccount{ + BaseAccount: baseAcc, + Name: ga.Name, + }, nil } From 34ff225c31170b82796e6ab43d6699d06f596308 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 14 Feb 2018 14:23:47 +0000 Subject: [PATCH 02/14] working --- baseapp/testapp.go | 5 +++++ examples/basecoin/app/app_test.go | 7 ++++++- examples/basecoin/types/account.go | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/baseapp/testapp.go b/baseapp/testapp.go index 389593d65..c4067ef3c 100644 --- a/baseapp/testapp.go +++ b/baseapp/testapp.go @@ -51,6 +51,11 @@ func (tapp *TestApp) RunBeginBlock() { return } +// kill resources used by basecapp +func (tapp *TestApp) Close() { + tapp.db.Close() +} + func (tapp *TestApp) ensureBeginBlock() { if tapp.header == nil { panic("TestApp.header was nil, call TestApp.RunBeginBlock()") diff --git a/examples/basecoin/app/app_test.go b/examples/basecoin/app/app_test.go index ce071eeed..2e0f24982 100644 --- a/examples/basecoin/app/app_test.go +++ b/examples/basecoin/app/app_test.go @@ -18,6 +18,7 @@ import ( func TestSendMsg(t *testing.T) { tba := newTestBasecoinApp() tba.RunBeginBlock() + defer tba.Close() // Construct a SendMsg. var msg = bank.SendMsg{ @@ -43,8 +44,12 @@ func TestSendMsg(t *testing.T) { // Run a Deliver on SendMsg. res = tba.RunDeliverMsg(msg) assert.Equal(t, sdk.CodeUnrecognizedAddress, res.Code, res.Log) +} - // TODO seperate this test, need a closer on db? keep getting resource unavailable +func TestGenesis(t *testing.T) { + tba := newTestBasecoinApp() + tba.RunBeginBlock() + defer tba.Close() // construct some genesis bytes to reflect basecoin/types/AppAccount pk := crypto.GenPrivKeyEd25519().PubKey() diff --git a/examples/basecoin/types/account.go b/examples/basecoin/types/account.go index 4316adc6f..d4bc7fba4 100644 --- a/examples/basecoin/types/account.go +++ b/examples/basecoin/types/account.go @@ -4,6 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" crypto "github.com/tendermint/go-crypto" + cmn "github.com/tendermint/tmlibs/common" ) var _ sdk.Account = (*AppAccount)(nil) From f446b94ac73020036509d867927f4042c1e468e4 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 14 Feb 2018 16:16:06 +0000 Subject: [PATCH 03/14] wip basecoin refactoring --- baseapp/baseapp.go | 68 ++++------- baseapp/genesis.go | 35 +----- baseapp/helpers.go | 24 ++++ examples/basecoin/app/app.go | 151 +++++++++++++++++------- examples/basecoin/app/app_test.go | 21 +++- examples/basecoin/app/init_baseapp.go | 94 --------------- examples/basecoin/app/init_capkeys.go | 16 --- examples/basecoin/app/init_handlers.go | 30 ----- examples/basecoin/app/init_stores.go | 38 ------ examples/basecoin/app/msgs.go | 2 +- examples/basecoin/app/testapp.go | 19 --- examples/basecoin/cmd/basecoind/main.go | 7 +- examples/basecoin/types/account.go | 36 +++--- 13 files changed, 204 insertions(+), 337 deletions(-) create mode 100644 baseapp/helpers.go delete mode 100644 examples/basecoin/app/init_baseapp.go delete mode 100644 examples/basecoin/app/init_capkeys.go delete mode 100644 examples/basecoin/app/init_handlers.go delete mode 100644 examples/basecoin/app/init_stores.go delete mode 100644 examples/basecoin/app/testapp.go diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index e92f58bdc..356dba0b6 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -8,6 +8,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/pkg/errors" + abci "github.com/tendermint/abci/types" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" @@ -21,44 +22,22 @@ var mainHeaderKey = []byte("header") // The ABCI application type BaseApp struct { - logger log.Logger - - // Application name from abci.Info - name string - - // Common DB backend - db dbm.DB - - // Main (uncached) state - cms sdk.CommitMultiStore - - // unmarshal []byte into sdk.Tx - txDecoder sdk.TxDecoder - - // unmarshal rawjsonbytes to initialize the application - // TODO unexpose and call from InitChain - InitStater sdk.InitStater - - // ante handler for fee and auth - defaultAnteHandler sdk.AnteHandler - - // handle any kind of message - router Router + logger log.Logger + name string // application name from abci.Info + db dbm.DB // common DB backend + cms sdk.CommitMultiStore // Main (uncached) state + txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx + InitStater sdk.InitStater // TODO unexpose + defaultAnteHandler sdk.AnteHandler // ante handler for fee and auth + router Router // handle any kind of message //-------------------- // Volatile - // CheckTx state, a cache-wrap of `.cms` - msCheck sdk.CacheMultiStore - - // DeliverTx state, a cache-wrap of `.cms` - msDeliver sdk.CacheMultiStore - - // current block header - header *abci.Header - - // cached validator changes from DeliverTx - valUpdates []abci.Validator + msCheck sdk.CacheMultiStore // CheckTx state, a cache-wrap of `.cms` + msDeliver sdk.CacheMultiStore // DeliverTx state, a cache-wrap of `.cms` + header *abci.Header // current block header + valUpdates []abci.Validator // cached validator changes from DeliverTx } var _ abci.Application = &BaseApp{} @@ -122,40 +101,40 @@ func (app *BaseApp) SetBeginBlocker(...) {} func (app *BaseApp) SetEndBlocker(...) {} */ -// TODO add description +// load latest application version func (app *BaseApp) LoadLatestVersion(mainKey sdk.StoreKey) error { app.cms.LoadLatestVersion() return app.initFromStore(mainKey) } -// Load application version +// load application version func (app *BaseApp) LoadVersion(version int64, mainKey sdk.StoreKey) error { app.cms.LoadVersion(version) return app.initFromStore(mainKey) } -// The last CommitID of the multistore. +// the last CommitID of the multistore func (app *BaseApp) LastCommitID() sdk.CommitID { return app.cms.LastCommitID() } -// The last commited block height. +// the last commited block height func (app *BaseApp) LastBlockHeight() int64 { return app.cms.LastCommitID().Version } -// Initializes the remaining logic from app.cms. +// initializes the remaining logic from app.cms func (app *BaseApp) initFromStore(mainKey sdk.StoreKey) error { var lastCommitID = app.cms.LastCommitID() var main = app.cms.GetKVStore(mainKey) var header *abci.Header - // Main store should exist. + // main store should exist. if main == nil { return errors.New("BaseApp expects MultiStore with 'main' KVStore") } - // If we've committed before, we expect main://. + // if we've committed before, we expect main:// if !lastCommitID.IsZero() { headerBytes := main.Get(mainHeaderKey) if len(headerBytes) == 0 { @@ -173,7 +152,7 @@ func (app *BaseApp) initFromStore(mainKey sdk.StoreKey) error { } } - // Set BaseApp state. + // set BaseApp state app.header = header app.msCheck = nil app.msDeliver = nil @@ -183,6 +162,7 @@ func (app *BaseApp) initFromStore(mainKey sdk.StoreKey) error { } //---------------------------------------- +// ABCI // Implements ABCI func (app *BaseApp) Info(req abci.RequestInfo) abci.ResponseInfo { @@ -205,7 +185,7 @@ func (app *BaseApp) SetOption(req abci.RequestSetOption) (res abci.ResponseSetOp // Implements ABCI func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) { // TODO: Use req.Validators - // TODO: Use req.AppStateJSON (?) + // TODO: Use req.AppState return } @@ -367,7 +347,7 @@ func (app *BaseApp) Commit() (res abci.ResponseCommit) { } //---------------------------------------- -// Misc. +// Helpers func (app *BaseApp) getMultiStore(isCheckTx bool) sdk.MultiStore { if isCheckTx { diff --git a/baseapp/genesis.go b/baseapp/genesis.go index 2baff9e51..c18d5e358 100644 --- a/baseapp/genesis.go +++ b/baseapp/genesis.go @@ -5,8 +5,7 @@ import ( "io/ioutil" ) -// TODO: remove from here and pass the AppState -// through InitChain +// TODO: remove from here and pass the AppState through InitChain // GenesisDoc defines the initial conditions for a tendermint blockchain, in particular its validator set. type GenesisDoc struct { @@ -14,12 +13,11 @@ type GenesisDoc struct { } // GenesisDocFromFile reads JSON data from a file and unmarshalls it into a GenesisDoc. -func GenesisDocFromFile(genDocFile string) (*GenesisDoc, error) { - if genDocFile == "" { - var g GenesisDoc - return &g, nil +func ReadGenesisAppState(genesisPath string) (state json.RawMessage, err error) { + if genesisPath == "" { + return } - jsonBlob, err := ioutil.ReadFile(genDocFile) + jsonBlob, err := ioutil.ReadFile(genesisPath) if err != nil { return nil, err } @@ -28,26 +26,5 @@ func GenesisDocFromFile(genDocFile string) (*GenesisDoc, error) { if err != nil { return nil, err } - return &genDoc, nil + return genDoc.AppState, nil } - -// read app state from the genesis file -//func GenesisAppState(genesisFile string) (state json.RawMessage, err error) { -//if genesisFile == "" { -//return -//} -//jsonBlob, err := ioutil.ReadFile(genesisFile) -//if err != nil { -//return nil, err -//} -//data := make(map[string]interface{}) -//err = json.Unmarshal(jsonBlob, &data) -//if err != nil { -//return nil, err -//} -//state, ok := data["app_state"].(json.RawMessage) -//if !ok { -//return nil, errors.New("app state genesis parse error") -//} -//return state, nil -//} diff --git a/baseapp/helpers.go b/baseapp/helpers.go new file mode 100644 index 000000000..43bd654d6 --- /dev/null +++ b/baseapp/helpers.go @@ -0,0 +1,24 @@ +package baseapp + +import ( + "github.com/tendermint/abci/server" + abci "github.com/tendermint/abci/types" + cmn "github.com/tendermint/tmlibs/common" +) + +// RunForever - BasecoinApp execution and cleanup +func RunForever(app abci.Application) { + + // Start the ABCI server + srv, err := server.NewServer("0.0.0.0:46658", "socket", app) + if err != nil { + cmn.Exit(err.Error()) + } + srv.Start() + + // Wait forever + cmn.TrapSignal(func() { + // Cleanup + srv.Stop() + }) +} diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index a7d27c580..67f871331 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -1,12 +1,16 @@ package app import ( + "encoding/json" "fmt" bam "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/examples/basecoin/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/sketchy" - "github.com/tendermint/abci/server" abci "github.com/tendermint/abci/types" "github.com/tendermint/go-wire" cmn "github.com/tendermint/tmlibs/common" @@ -28,63 +32,130 @@ type BasecoinApp struct { accountMapper sdk.AccountMapper } -// TODO: This should take in more configuration options. -// TODO: This should be moved into baseapp to isolate complexity +// construct top level keys +func (app *BasecoinApp) initCapKeys() { + app.capKeyMainStore = sdk.NewKVStoreKey("main") + app.capKeyIBCStore = sdk.NewKVStoreKey("ibc") +} + +func (app *BasecoinApp) initDefaultAnteHandler() { + // deducts fee from payer, verifies signatures and nonces, sets Signers to ctx. + app.BaseApp.SetDefaultAnteHandler(auth.NewAnteHandler(app.accountMapper)) +} + +func (app *BasecoinApp) initRouterHandlers() { + + // All handlers must be added here, the order matters + app.router.AddRoute("bank", bank.NewHandler(bank.NewCoinKeeper(app.accountMapper))) + app.router.AddRoute("sketchy", sketchy.NewHandler()) +} + +func (app *BasecoinApp) initBaseAppTxDecoder() { + cdc := makeTxCodec() + app.BaseApp.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) { + var tx = sdk.StdTx{} + // StdTx.Msg is an interface whose concrete + // types are registered in app/msgs.go. + err := cdc.UnmarshalBinary(txBytes, &tx) + if err != nil { + return nil, sdk.ErrTxParse("").TraceCause(err, "") + } + return tx, nil + }) +} + +// define the custom logic for basecoin initialization +func (app *BasecoinApp) initBaseAppInitStater() { + accountMapper := app.accountMapper + + app.BaseApp.SetInitStater(func(ctx sdk.Context, state json.RawMessage) sdk.Error { + if state == nil { + return nil + } + + genesisState := new(types.GenesisState) + err := json.Unmarshal(state, genesisState) + if err != nil { + return sdk.ErrGenesisParse("").TraceCause(err, "") + } + + for _, gacc := range genesisState.Accounts { + acc, err := gacc.ToAppAccount() + if err != nil { + return sdk.ErrGenesisParse("").TraceCause(err, "") + } + accountMapper.SetAccount(ctx, acc) + } + return nil + }) +} + +// Initialize root stores. +func (app *BasecoinApp) mountStores() { + + // Create MultiStore mounts. + app.BaseApp.MountStore(app.capKeyMainStore, sdk.StoreTypeIAVL) + app.BaseApp.MountStore(app.capKeyIBCStore, sdk.StoreTypeIAVL) +} + +// Initialize the AccountMapper. +func (app *BasecoinApp) initAccountMapper() { + + var accountMapper = auth.NewAccountMapper( + app.capKeyMainStore, // target store + &types.AppAccount{}, // prototype + ) + + // Register all interfaces and concrete types that + // implement those interfaces, here. + cdc := accountMapper.WireCodec() + auth.RegisterWireBaseAccount(cdc) + + // Make accountMapper's WireCodec() inaccessible. + app.accountMapper = accountMapper.Seal() +} + func NewBasecoinApp(genesisPath string) *BasecoinApp { - // Create and configure app. + // create and configure app var app = &BasecoinApp{} + bapp := bam.NewBaseApp(appName) + app.BaseApp = bapp + app.router = bapp.Router() + app.initBaseAppTxDecoder() - // TODO open up out of functions, or introduce clarity, - // interdependancies are a nightmare to debug - app.initCapKeys() // ./init_capkeys.go - app.initBaseApp() // ./init_baseapp.go - app.initStores() // ./init_stores.go + // add keys + app.initCapKeys() + + // initialize the stores + app.mountStores() + app.initAccountMapper() + + // initialize the genesis function app.initBaseAppInitStater() - app.initHandlers() // ./init_handlers.go - genesisiDoc, err := bam.GenesisDocFromFile(genesisPath) + // initialize the handler + app.initDefaultAnteHandler() + app.initRouterHandlers() + + genesisAppState, err := bam.ReadGenesisAppState(genesisPath) if err != nil { panic(fmt.Errorf("error loading genesis state: %v", err)) } // set up the cache store for ctx, get ctx - // TODO: can InitChain handle this too ? + // TODO: combine with InitChain and let tendermint invoke it. app.BaseApp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{}}) ctx := app.BaseApp.NewContext(false, nil) // context for DeliverTx - - // TODO: combine with InitChain and let tendermint invoke it. - err = app.BaseApp.InitStater(ctx, genesisiDoc.AppState) + err = app.BaseApp.InitStater(ctx, genesisAppState) if err != nil { panic(fmt.Errorf("error initializing application genesis state: %v", err)) } - app.loadStores() - - return app -} - -// RunForever - BasecoinApp execution and cleanup -func (app *BasecoinApp) RunForever() { - - // Start the ABCI server - srv, err := server.NewServer("0.0.0.0:46658", "socket", app) - if err != nil { - cmn.Exit(err.Error()) - } - srv.Start() - - // Wait forever - cmn.TrapSignal(func() { - // Cleanup - srv.Stop() - }) - -} - -// Load the stores -func (app *BasecoinApp) loadStores() { + // load the stores if err := app.LoadLatestVersion(app.capKeyMainStore); err != nil { cmn.Exit(err.Error()) } + + return app } diff --git a/examples/basecoin/app/app_test.go b/examples/basecoin/app/app_test.go index 2e0f24982..2014fef7c 100644 --- a/examples/basecoin/app/app_test.go +++ b/examples/basecoin/app/app_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + bam "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/examples/basecoin/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" @@ -15,6 +16,20 @@ import ( crypto "github.com/tendermint/go-crypto" ) +type testBasecoinApp struct { + *BasecoinApp + *bam.TestApp +} + +func newTestBasecoinApp() *testBasecoinApp { + app := NewBasecoinApp("") + tba := &testBasecoinApp{ + BasecoinApp: app, + } + tba.TestApp = bam.NewTestApp(app.BaseApp) + return tba +} + func TestSendMsg(t *testing.T) { tba := newTestBasecoinApp() tba.RunBeginBlock() @@ -62,9 +77,9 @@ func TestGenesis(t *testing.T) { } acc := &types.AppAccount{baseAcc, "foobart"} - genesisState := GenesisState{ - Accounts: []*GenesisAccount{ - NewGenesisAccount(acc), + genesisState := types.GenesisState{ + Accounts: []*types.GenesisAccount{ + types.NewGenesisAccount(acc), }, } bytes, err := json.MarshalIndent(genesisState, "", "\t") diff --git a/examples/basecoin/app/init_baseapp.go b/examples/basecoin/app/init_baseapp.go deleted file mode 100644 index 4ab701a9f..000000000 --- a/examples/basecoin/app/init_baseapp.go +++ /dev/null @@ -1,94 +0,0 @@ -package app - -import ( - "encoding/json" - - "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/examples/basecoin/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth" - crypto "github.com/tendermint/go-crypto" -) - -// initCapKeys, initBaseApp, initStores, initHandlers. -func (app *BasecoinApp) initBaseApp() { - bapp := baseapp.NewBaseApp(appName) - app.BaseApp = bapp - app.router = bapp.Router() - app.initBaseAppTxDecoder() - app.initBaseAppInitStater() -} - -func (app *BasecoinApp) initBaseAppTxDecoder() { - cdc := makeTxCodec() - app.BaseApp.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) { - var tx = sdk.StdTx{} - // StdTx.Msg is an interface whose concrete - // types are registered in app/msgs.go. - err := cdc.UnmarshalBinary(txBytes, &tx) - if err != nil { - return nil, sdk.ErrTxParse("").TraceCause(err, "") - } - return tx, nil - }) -} - -// define the custom logic for basecoin initialization -func (app *BasecoinApp) initBaseAppInitStater() { - accountMapper := app.accountMapper - - app.BaseApp.SetInitStater(func(ctx sdk.Context, state json.RawMessage) sdk.Error { - if state == nil { - return nil - } - - genesisState := new(GenesisState) - err := json.Unmarshal(state, genesisState) - if err != nil { - return sdk.ErrGenesisParse("").TraceCause(err, "") - } - - for _, gacc := range genesisState.Accounts { - acc, err := gacc.toAppAccount() - if err != nil { - return sdk.ErrGenesisParse("").TraceCause(err, "") - } - accountMapper.SetAccount(ctx, acc) - } - return nil - }) -} - -//----------------------------------------------------- - -// State to Unmarshal -type GenesisState struct { - Accounts []*GenesisAccount `accounts` -} - -// GenesisAccount doesn't need pubkey or sequence -type GenesisAccount struct { - Name string `json:"name"` - Address crypto.Address `json:"address"` - Coins sdk.Coins `json:"coins"` -} - -func NewGenesisAccount(aa *types.AppAccount) *GenesisAccount { - return &GenesisAccount{ - Name: aa.Name, - Address: aa.Address, - Coins: aa.Coins, - } -} - -// convert GenesisAccount to AppAccount -func (ga *GenesisAccount) toAppAccount() (acc *types.AppAccount, err error) { - baseAcc := auth.BaseAccount{ - Address: ga.Address, - Coins: ga.Coins, - } - return &types.AppAccount{ - BaseAccount: baseAcc, - Name: ga.Name, - }, nil -} diff --git a/examples/basecoin/app/init_capkeys.go b/examples/basecoin/app/init_capkeys.go deleted file mode 100644 index 7327c6184..000000000 --- a/examples/basecoin/app/init_capkeys.go +++ /dev/null @@ -1,16 +0,0 @@ -package app - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// initCapKeys, initBaseApp, initStores, initHandlers. -func (app *BasecoinApp) initCapKeys() { - - // All top-level capabilities keys - // should be constructed here. - // For more information, see http://www.erights.org/elib/capability/ode/ode.pdf. - app.capKeyMainStore = sdk.NewKVStoreKey("main") - app.capKeyIBCStore = sdk.NewKVStoreKey("ibc") - -} diff --git a/examples/basecoin/app/init_handlers.go b/examples/basecoin/app/init_handlers.go deleted file mode 100644 index 62831514b..000000000 --- a/examples/basecoin/app/init_handlers.go +++ /dev/null @@ -1,30 +0,0 @@ -package app - -import ( - "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/bank" - "github.com/cosmos/cosmos-sdk/x/sketchy" -) - -// initCapKeys, initBaseApp, initStores, initHandlers. -func (app *BasecoinApp) initHandlers() { - app.initDefaultAnteHandler() - app.initRouterHandlers() -} - -func (app *BasecoinApp) initDefaultAnteHandler() { - - // Deducts fee from payer. - // Verifies signatures and nonces. - // Sets Signers to ctx. - app.BaseApp.SetDefaultAnteHandler( - auth.NewAnteHandler(app.accountMapper)) -} - -func (app *BasecoinApp) initRouterHandlers() { - - // All handlers must be added here. - // The order matters. - app.router.AddRoute("bank", bank.NewHandler(bank.NewCoinKeeper(app.accountMapper))) - app.router.AddRoute("sketchy", sketchy.NewHandler()) -} diff --git a/examples/basecoin/app/init_stores.go b/examples/basecoin/app/init_stores.go deleted file mode 100644 index e819ecd2c..000000000 --- a/examples/basecoin/app/init_stores.go +++ /dev/null @@ -1,38 +0,0 @@ -package app - -import ( - "github.com/cosmos/cosmos-sdk/examples/basecoin/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth" -) - -// initCapKeys, initBaseApp, initStores, initHandlers. -func (app *BasecoinApp) initStores() { - app.mountStores() - app.initAccountMapper() -} - -// Initialize root stores. -func (app *BasecoinApp) mountStores() { - - // Create MultiStore mounts. - app.BaseApp.MountStore(app.capKeyMainStore, sdk.StoreTypeIAVL) - app.BaseApp.MountStore(app.capKeyIBCStore, sdk.StoreTypeIAVL) -} - -// Initialize the AccountMapper. -func (app *BasecoinApp) initAccountMapper() { - - var accountMapper = auth.NewAccountMapper( - app.capKeyMainStore, // target store - &types.AppAccount{}, // prototype - ) - - // Register all interfaces and concrete types that - // implement those interfaces, here. - cdc := accountMapper.WireCodec() - auth.RegisterWireBaseAccount(cdc) - - // Make accountMapper's WireCodec() inaccessible. - app.accountMapper = accountMapper.Seal() -} diff --git a/examples/basecoin/app/msgs.go b/examples/basecoin/app/msgs.go index a8ec883bd..c1273dfbc 100644 --- a/examples/basecoin/app/msgs.go +++ b/examples/basecoin/app/msgs.go @@ -6,7 +6,7 @@ import ( wire "github.com/tendermint/go-wire" ) -// Wire requires registration of interfaces & concrete types. All +// Wire requires registration of interfaces & concrete types. All // interfaces to be encoded/decoded in a Msg must be registered // here, along with all the concrete types that implement them. func makeTxCodec() (cdc *wire.Codec) { diff --git a/examples/basecoin/app/testapp.go b/examples/basecoin/app/testapp.go deleted file mode 100644 index 8603911d5..000000000 --- a/examples/basecoin/app/testapp.go +++ /dev/null @@ -1,19 +0,0 @@ -package app - -import ( - bam "github.com/cosmos/cosmos-sdk/baseapp" -) - -type testBasecoinApp struct { - *BasecoinApp - *bam.TestApp -} - -func newTestBasecoinApp() *testBasecoinApp { - app := NewBasecoinApp("") - tba := &testBasecoinApp{ - BasecoinApp: app, - } - tba.TestApp = bam.NewTestApp(app.BaseApp) - return tba -} diff --git a/examples/basecoin/cmd/basecoind/main.go b/examples/basecoin/cmd/basecoind/main.go index 623bb35e4..dff41d0b8 100644 --- a/examples/basecoin/cmd/basecoind/main.go +++ b/examples/basecoin/cmd/basecoind/main.go @@ -1,10 +1,13 @@ package main -import "github.com/cosmos/cosmos-sdk/examples/basecoin/app" +import ( + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/examples/basecoin/app" +) func main() { // TODO CREATE CLI bapp := app.NewBasecoinApp("") - bapp.RunForever() + baseapp.RunForever(bapp) } diff --git a/examples/basecoin/types/account.go b/examples/basecoin/types/account.go index d4bc7fba4..3177f9912 100644 --- a/examples/basecoin/types/account.go +++ b/examples/basecoin/types/account.go @@ -4,7 +4,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" crypto "github.com/tendermint/go-crypto" - cmn "github.com/tendermint/tmlibs/common" ) var _ sdk.Account = (*AppAccount)(nil) @@ -25,36 +24,31 @@ func (acc *AppAccount) SetName(name string) { acc.Name = name } //___________________________________________________________________________________ -// We use GenesisAccount instead of AppAccount for cleaner json input of PubKey +// State to Unmarshal +type GenesisState struct { + Accounts []*GenesisAccount `json:"accounts"` +} + +// GenesisAccount doesn't need pubkey or sequence type GenesisAccount struct { - Name string `json:"name"` - Address crypto.Address `json:"address"` - Coins sdk.Coins `json:"coins"` - PubKey cmn.HexBytes `json:"public_key"` - Sequence int64 `json:"sequence"` + Name string `json:"name"` + Address crypto.Address `json:"address"` + Coins sdk.Coins `json:"coins"` } func NewGenesisAccount(aa *AppAccount) *GenesisAccount { return &GenesisAccount{ - Name: aa.Name, - Address: aa.Address, - Coins: aa.Coins, - PubKey: aa.PubKey.Bytes(), - Sequence: aa.Sequence, + Name: aa.Name, + Address: aa.Address, + Coins: aa.Coins, } } // convert GenesisAccount to AppAccount -func (ga *GenesisAccount) toAppAccount() (acc *AppAccount, err error) { - pk, err := crypto.PubKeyFromBytes(ga.PubKey) - if err != nil { - return - } +func (ga *GenesisAccount) ToAppAccount() (acc *AppAccount, err error) { baseAcc := auth.BaseAccount{ - Address: ga.Address, - Coins: ga.Coins, - PubKey: pk, - Sequence: ga.Sequence, + Address: ga.Address, + Coins: ga.Coins, } return &AppAccount{ BaseAccount: baseAcc, From 44536faf08a8d0697deb431604df9a2bbacced33 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 14 Feb 2018 19:14:22 +0000 Subject: [PATCH 04/14] wip refactoring basecoin --- baseapp/baseapp.go | 55 +++++++++++-- examples/basecoin/app/app.go | 149 +++++++++++++--------------------- examples/basecoin/app/msgs.go | 22 ----- x/auth/mapper.go | 13 +++ 4 files changed, 117 insertions(+), 122 deletions(-) delete mode 100644 examples/basecoin/app/msgs.go diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 356dba0b6..941c0eaf4 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -16,6 +16,7 @@ import ( "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" ) var mainHeaderKey = []byte("header") @@ -34,10 +35,11 @@ type BaseApp struct { //-------------------- // Volatile - msCheck sdk.CacheMultiStore // CheckTx state, a cache-wrap of `.cms` - msDeliver sdk.CacheMultiStore // DeliverTx state, a cache-wrap of `.cms` - header *abci.Header // current block header - valUpdates []abci.Validator // cached validator changes from DeliverTx + accountMapper sdk.AccountMapper // Manage getting and setting accounts + msCheck sdk.CacheMultiStore // CheckTx state, a cache-wrap of `.cms` + msDeliver sdk.CacheMultiStore // DeliverTx state, a cache-wrap of `.cms` + header *abci.Header // current block header + valUpdates []abci.Validator // cached validator changes from DeliverTx } var _ abci.Application = &BaseApp{} @@ -53,9 +55,44 @@ func NewBaseApp(name string) *BaseApp { } baseapp.initDB() baseapp.initMultiStore() + return baseapp } +// Create and name new BaseApp +func NewBaseAppExpanded(name string, accountMapper sdk.AccountMapper, keys []*sdk.KVStoreKey) *BaseApp { + var baseapp = &BaseApp{ + logger: makeDefaultLogger(), + name: name, + db: nil, + cms: nil, + defaultAnteHandler: auth.NewAnteHandler(app.AccountMapper()), + router: NewRouter(), + accountMapper: accountMapper, + } + baseapp.initDB() + baseapp.initMultiStore() + baseapp.initAccountMapper() + + for _, key := range keys { + baseApp.MountStore(key, sdk.StoreTypeIAVL) + } + + return baseapp +} + +// Initialize the AccountMapper. +func (app *BaseApp) initAccountMapper() { + + // Register all interfaces and concrete types that + // implement those interfaces, here. + cdc := accountMapper.WireCodec() + auth.RegisterWireBaseAccount(cdc) + + // Make accountMapper's WireCodec() inaccessible. + app.accountMapper = accountMapper.Seal() +} + // Create the underlying leveldb datastore which will // persist the Merkle tree inner & leaf nodes. func (app *BaseApp) initDB() { @@ -82,7 +119,7 @@ func (app *BaseApp) MountStore(key sdk.StoreKey, typ sdk.StoreType) { app.cms.MountStoreWithDB(key, typ, app.db) } -// nolint +// nolint - Set functions func (app *BaseApp) SetTxDecoder(txDecoder sdk.TxDecoder) { app.txDecoder = txDecoder } @@ -90,11 +127,13 @@ func (app *BaseApp) SetInitStater(initStater sdk.InitStater) { app.InitStater = initStater } func (app *BaseApp) SetDefaultAnteHandler(ah sdk.AnteHandler) { + // deducts fee from payer, verifies signatures and nonces, sets Signers to ctx. app.defaultAnteHandler = ah } -func (app *BaseApp) Router() Router { - return app.router -} + +// nolint - Get functions +func (app *BaseApp) Router() Router { return app.router } +func (app *BaseApp) AccountMapper() sdk.AccountMapper { return app.accountMapper } /* TODO consider: func (app *BaseApp) SetBeginBlocker(...) {} diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index 67f871331..ead962e12 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/sketchy" abci "github.com/tendermint/abci/types" + crypto "github.com/tendermint/go-crypto" "github.com/tendermint/go-wire" cmn "github.com/tendermint/tmlibs/common" ) @@ -21,42 +22,63 @@ const appName = "BasecoinApp" // Extended ABCI application type BasecoinApp struct { *bam.BaseApp - router bam.Router - cdc *wire.Codec + cdc *wire.Codec // keys to access the substores capKeyMainStore *sdk.KVStoreKey capKeyIBCStore *sdk.KVStoreKey - - // object mappers - accountMapper sdk.AccountMapper } -// construct top level keys -func (app *BasecoinApp) initCapKeys() { - app.capKeyMainStore = sdk.NewKVStoreKey("main") - app.capKeyIBCStore = sdk.NewKVStoreKey("ibc") +func NewBasecoinApp(genesisPath string) *BasecoinApp { + + var app = &BasecoinApp{ + cdc: makeCodex(), + capKeyMainStore: sdk.NewKVStoreKey("main"), + capKeyIBCStore: sdk.NewKVStoreKey("ibc"), + } + + var accMapper = auth.NewAccountMapper( + app.capKeyMainStore, // target store + &types.AppAccount{}, // prototype + ) + + app.BaseApp = bam.NewBaseAppExpanded(appName, accMapper) + app.initBaseAppTxDecoder() + app.initBaseAppInitStater(genesisPath) + + // Add the handlers + app.Router().AddRoute("bank", bank.NewHandler(bank.NewCoinKeeper(app.AccountMapper()))) + app.Router().AddRoute("sketchy", sketchy.NewHandler()) + + // load the stores + if err := app.LoadLatestVersion(app.capKeyMainStore); err != nil { + cmn.Exit(err.Error()) + } + + return app } -func (app *BasecoinApp) initDefaultAnteHandler() { - // deducts fee from payer, verifies signatures and nonces, sets Signers to ctx. - app.BaseApp.SetDefaultAnteHandler(auth.NewAnteHandler(app.accountMapper)) -} +// Wire requires registration of interfaces & concrete types. All +// interfaces to be encoded/decoded in a Msg must be registered +// here, along with all the concrete types that implement them. +func makeTxCodec() (cdc *wire.Codec) { + cdc = wire.NewCodec() -func (app *BasecoinApp) initRouterHandlers() { + // Register crypto.[PubKey,PrivKey,Signature] types. + crypto.RegisterWire(cdc) - // All handlers must be added here, the order matters - app.router.AddRoute("bank", bank.NewHandler(bank.NewCoinKeeper(app.accountMapper))) - app.router.AddRoute("sketchy", sketchy.NewHandler()) + // Register bank.[SendMsg,IssueMsg] types. + bank.RegisterWire(cdc) + + return } func (app *BasecoinApp) initBaseAppTxDecoder() { - cdc := makeTxCodec() app.BaseApp.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) { var tx = sdk.StdTx{} // StdTx.Msg is an interface whose concrete // types are registered in app/msgs.go. - err := cdc.UnmarshalBinary(txBytes, &tx) + err := app.cdc.UnmarshalBinary(txBytes, &tx) if err != nil { return nil, sdk.ErrTxParse("").TraceCause(err, "") } @@ -65,8 +87,21 @@ func (app *BasecoinApp) initBaseAppTxDecoder() { } // define the custom logic for basecoin initialization -func (app *BasecoinApp) initBaseAppInitStater() { - accountMapper := app.accountMapper +func (app *BasecoinApp) initBaseAppInitStater(genesisPath string) { + + genesisAppState, err := bam.ReadGenesisAppState(genesisPath) + if err != nil { + panic(fmt.Errorf("error loading genesis state: %v", err)) + } + + // set up the cache store for ctx, get ctx + // TODO: combine with InitChain and let tendermint invoke it. + app.BaseApp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{}}) + ctx := app.BaseApp.NewContext(false, nil) // context for DeliverTx + err = app.BaseApp.InitStater(ctx, genesisAppState) + if err != nil { + cmn.Exit(fmt.Sprintf("error initializing application genesis state: %v", err)) + } app.BaseApp.SetInitStater(func(ctx sdk.Context, state json.RawMessage) sdk.Error { if state == nil { @@ -84,78 +119,8 @@ func (app *BasecoinApp) initBaseAppInitStater() { if err != nil { return sdk.ErrGenesisParse("").TraceCause(err, "") } - accountMapper.SetAccount(ctx, acc) + app.AccountMapper().SetAccount(ctx, acc) } return nil }) } - -// Initialize root stores. -func (app *BasecoinApp) mountStores() { - - // Create MultiStore mounts. - app.BaseApp.MountStore(app.capKeyMainStore, sdk.StoreTypeIAVL) - app.BaseApp.MountStore(app.capKeyIBCStore, sdk.StoreTypeIAVL) -} - -// Initialize the AccountMapper. -func (app *BasecoinApp) initAccountMapper() { - - var accountMapper = auth.NewAccountMapper( - app.capKeyMainStore, // target store - &types.AppAccount{}, // prototype - ) - - // Register all interfaces and concrete types that - // implement those interfaces, here. - cdc := accountMapper.WireCodec() - auth.RegisterWireBaseAccount(cdc) - - // Make accountMapper's WireCodec() inaccessible. - app.accountMapper = accountMapper.Seal() -} - -func NewBasecoinApp(genesisPath string) *BasecoinApp { - - // create and configure app - var app = &BasecoinApp{} - bapp := bam.NewBaseApp(appName) - app.BaseApp = bapp - app.router = bapp.Router() - app.initBaseAppTxDecoder() - - // add keys - app.initCapKeys() - - // initialize the stores - app.mountStores() - app.initAccountMapper() - - // initialize the genesis function - app.initBaseAppInitStater() - - // initialize the handler - app.initDefaultAnteHandler() - app.initRouterHandlers() - - genesisAppState, err := bam.ReadGenesisAppState(genesisPath) - if err != nil { - panic(fmt.Errorf("error loading genesis state: %v", err)) - } - - // set up the cache store for ctx, get ctx - // TODO: combine with InitChain and let tendermint invoke it. - app.BaseApp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{}}) - ctx := app.BaseApp.NewContext(false, nil) // context for DeliverTx - err = app.BaseApp.InitStater(ctx, genesisAppState) - if err != nil { - panic(fmt.Errorf("error initializing application genesis state: %v", err)) - } - - // load the stores - if err := app.LoadLatestVersion(app.capKeyMainStore); err != nil { - cmn.Exit(err.Error()) - } - - return app -} diff --git a/examples/basecoin/app/msgs.go b/examples/basecoin/app/msgs.go deleted file mode 100644 index c1273dfbc..000000000 --- a/examples/basecoin/app/msgs.go +++ /dev/null @@ -1,22 +0,0 @@ -package app - -import ( - "github.com/cosmos/cosmos-sdk/x/bank" - crypto "github.com/tendermint/go-crypto" - wire "github.com/tendermint/go-wire" -) - -// Wire requires registration of interfaces & concrete types. All -// interfaces to be encoded/decoded in a Msg must be registered -// here, along with all the concrete types that implement them. -func makeTxCodec() (cdc *wire.Codec) { - cdc = wire.NewCodec() - - // Register crypto.[PubKey,PrivKey,Signature] types. - crypto.RegisterWire(cdc) - - // Register bank.[SendMsg,IssueMsg] types. - bank.RegisterWire(cdc) - - return -} diff --git a/x/auth/mapper.go b/x/auth/mapper.go index cccc774a3..fb69975f8 100644 --- a/x/auth/mapper.go +++ b/x/auth/mapper.go @@ -36,6 +36,19 @@ func NewAccountMapper(key sdk.StoreKey, proto sdk.Account) accountMapper { } } +// XXX add comment +func NewAccountMapperSealed(key sdk.StoreKey, proto sdk.Account) accountMapper { + cdc := wire.NewCodec() + am := accountMapper{ + key: key, + proto: proto, + cdc: cdc, + } + RegisterWireBaseAccount(cdc) + am.Seal() + return am +} + // Returns the go-wire codec. You may need to register interfaces // and concrete types here, if your app's sdk.Account // implementation includes interface fields. From 6681904af9c9416c303855b78e65f0c64fb90207 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 15 Feb 2018 01:09:00 +0000 Subject: [PATCH 05/14] wip refactoring basecoin --- baseapp/baseapp.go | 86 ++++++++++++------------------- baseapp/baseapp_test.go | 2 +- baseapp/context.go | 19 ++++--- baseapp/genesis.go | 2 +- baseapp/{ => testapp}/testapp.go | 34 ++++-------- baseapp/testapp/x/tx.go | 22 ++++++++ examples/basecoin/app/app.go | 50 ++++++++++-------- examples/basecoin/app/app_test.go | 2 +- x/auth/ante.go | 10 ++-- 9 files changed, 110 insertions(+), 117 deletions(-) rename baseapp/{ => testapp}/testapp.go (77%) create mode 100644 baseapp/testapp/x/tx.go diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 941c0eaf4..63bf6f764 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -16,30 +16,28 @@ import ( "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth" ) var mainHeaderKey = []byte("header") // The ABCI application type BaseApp struct { - logger log.Logger - name string // application name from abci.Info - db dbm.DB // common DB backend - cms sdk.CommitMultiStore // Main (uncached) state - txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx - InitStater sdk.InitStater // TODO unexpose - defaultAnteHandler sdk.AnteHandler // ante handler for fee and auth - router Router // handle any kind of message + logger log.Logger + name string // application name from abci.Info + db dbm.DB // common DB backend + cms sdk.CommitMultiStore // Main (uncached) state + txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx + InitStater sdk.InitStater // TODO unexpose + anteHandler sdk.AnteHandler // ante handler for fee and auth + router Router // handle any kind of message //-------------------- // Volatile - accountMapper sdk.AccountMapper // Manage getting and setting accounts - msCheck sdk.CacheMultiStore // CheckTx state, a cache-wrap of `.cms` - msDeliver sdk.CacheMultiStore // DeliverTx state, a cache-wrap of `.cms` - header *abci.Header // current block header - valUpdates []abci.Validator // cached validator changes from DeliverTx + msCheck sdk.CacheMultiStore // CheckTx state, a cache-wrap of `.cms` + msDeliver sdk.CacheMultiStore // DeliverTx state, a cache-wrap of `.cms` + header *abci.Header // current block header + valUpdates []abci.Validator // cached validator changes from DeliverTx } var _ abci.Application = &BaseApp{} @@ -59,40 +57,6 @@ func NewBaseApp(name string) *BaseApp { return baseapp } -// Create and name new BaseApp -func NewBaseAppExpanded(name string, accountMapper sdk.AccountMapper, keys []*sdk.KVStoreKey) *BaseApp { - var baseapp = &BaseApp{ - logger: makeDefaultLogger(), - name: name, - db: nil, - cms: nil, - defaultAnteHandler: auth.NewAnteHandler(app.AccountMapper()), - router: NewRouter(), - accountMapper: accountMapper, - } - baseapp.initDB() - baseapp.initMultiStore() - baseapp.initAccountMapper() - - for _, key := range keys { - baseApp.MountStore(key, sdk.StoreTypeIAVL) - } - - return baseapp -} - -// Initialize the AccountMapper. -func (app *BaseApp) initAccountMapper() { - - // Register all interfaces and concrete types that - // implement those interfaces, here. - cdc := accountMapper.WireCodec() - auth.RegisterWireBaseAccount(cdc) - - // Make accountMapper's WireCodec() inaccessible. - app.accountMapper = accountMapper.Seal() -} - // Create the underlying leveldb datastore which will // persist the Merkle tree inner & leaf nodes. func (app *BaseApp) initDB() { @@ -114,6 +78,13 @@ func (app *BaseApp) Name() string { return app.name } +// Mount a store to the provided key in the BaseApp multistore +func (app *BaseApp) MountStoresIAVL(keys ...*sdk.KVStoreKey) { + for _, key := range keys { + app.MountStore(key, sdk.StoreTypeIAVL) + } +} + // Mount a store to the provided key in the BaseApp multistore func (app *BaseApp) MountStore(key sdk.StoreKey, typ sdk.StoreType) { app.cms.MountStoreWithDB(key, typ, app.db) @@ -126,14 +97,13 @@ func (app *BaseApp) SetTxDecoder(txDecoder sdk.TxDecoder) { func (app *BaseApp) SetInitStater(initStater sdk.InitStater) { app.InitStater = initStater } -func (app *BaseApp) SetDefaultAnteHandler(ah sdk.AnteHandler) { +func (app *BaseApp) SetAnteHandler(ah sdk.AnteHandler) { // deducts fee from payer, verifies signatures and nonces, sets Signers to ctx. - app.defaultAnteHandler = ah + app.anteHandler = ah } // nolint - Get functions -func (app *BaseApp) Router() Router { return app.router } -func (app *BaseApp) AccountMapper() sdk.AccountMapper { return app.accountMapper } +func (app *BaseApp) Router() Router { return app.router } /* TODO consider: func (app *BaseApp) SetBeginBlocker(...) {} @@ -224,7 +194,15 @@ func (app *BaseApp) SetOption(req abci.RequestSetOption) (res abci.ResponseSetOp // Implements ABCI func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) { // TODO: Use req.Validators - // TODO: Use req.AppState + // TODO: Use req.AppState in InitStater + + app.msDeliver = app.cms.CacheMultiStore() + ctx := app.GenesisContext(nil) + + err := app.InitStater(ctx, nil) + if err != nil { + cmn.Exit(fmt.Sprintf("error initializing application genesis state: %v", err)) + } return } @@ -338,7 +316,7 @@ func (app *BaseApp) runTx(isCheckTx bool, txBytes []byte, tx sdk.Tx) (result sdk // TODO: override default ante handler w/ custom ante handler. // Run the ante handler. - newCtx, result, abort := app.defaultAnteHandler(ctx, tx) + newCtx, result, abort := app.anteHandler(ctx, tx) if isCheckTx || abort { return result } diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index 7ceaacd20..695115729 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -44,7 +44,7 @@ func TestBasic(t *testing.T) { return ttx, nil }) - app.SetDefaultAnteHandler(func(ctx sdk.Context, tx sdk.Tx) (newCtx sdk.Context, res sdk.Result, abort bool) { return }) + app.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx) (newCtx sdk.Context, res sdk.Result, abort bool) { return }) app.Router().AddRoute(msgType, func(ctx sdk.Context, msg sdk.Msg) sdk.Result { // TODO return sdk.Result{} diff --git a/baseapp/context.go b/baseapp/context.go index e5a60f967..8ac10bce7 100644 --- a/baseapp/context.go +++ b/baseapp/context.go @@ -2,6 +2,7 @@ package baseapp import ( sdk "github.com/cosmos/cosmos-sdk/types" + abci "github.com/tendermint/abci/types" ) // NewContext returns a new Context suitable for AnteHandler (and indirectly Handler) processing. @@ -22,12 +23,14 @@ func (app *BaseApp) NewContext(isCheckTx bool, txBytes []byte) sdk.Context { panic("BaseApp.NewContext() requires BeginBlock(): missing header") } - // Initialize arguments to Handler. - var ctx = sdk.NewContext( - store, - *app.header, - isCheckTx, - txBytes, - ) - return ctx + return sdk.NewContext(store, *app.header, isCheckTx, txBytes) +} + +// context used during genesis +func (app *BaseApp) GenesisContext(txBytes []byte) sdk.Context { + store := app.msDeliver + if store == nil { + panic("BaseApp.NewContext() requires BeginBlock(): missing store") + } + return sdk.NewContext(store, abci.Header{}, false, txBytes) } diff --git a/baseapp/genesis.go b/baseapp/genesis.go index c18d5e358..acd7d7688 100644 --- a/baseapp/genesis.go +++ b/baseapp/genesis.go @@ -13,7 +13,7 @@ type GenesisDoc struct { } // GenesisDocFromFile reads JSON data from a file and unmarshalls it into a GenesisDoc. -func ReadGenesisAppState(genesisPath string) (state json.RawMessage, err error) { +func LoadGenesisAppState(genesisPath string) (state json.RawMessage, err error) { if genesisPath == "" { return } diff --git a/baseapp/testapp.go b/baseapp/testapp/testapp.go similarity index 77% rename from baseapp/testapp.go rename to baseapp/testapp/testapp.go index c4067ef3c..a80c494f4 100644 --- a/baseapp/testapp.go +++ b/baseapp/testapp/testapp.go @@ -1,23 +1,24 @@ -package baseapp +package testapp import ( abci "github.com/tendermint/abci/types" - "github.com/tendermint/go-crypto" + bam "github.com/cosmos/cosmos-sdk/baseapp" + x "github.com/cosmos/cosmos-sdk/baseapp/testapp/x" sdk "github.com/cosmos/cosmos-sdk/types" ) // TestApp wraps BaseApp with helper methods, // and exposes more functionality than otherwise needed. type TestApp struct { - *BaseApp + *bam.BaseApp // These get set as we receive them. *abci.ResponseBeginBlock *abci.ResponseEndBlock } -func NewTestApp(bapp *BaseApp) *TestApp { +func NewTestApp(bapp *bam.BaseApp) *TestApp { app := &TestApp{ BaseApp: bapp, } @@ -75,16 +76,16 @@ func (tapp *TestApp) RunDeliverTx(tx sdk.Tx) sdk.Result { } // run tx through CheckTx of TestApp -// NOTE: Skips authentication by wrapping msg in testTx{}. +// NOTE: Skips authentication by wrapping msg in TestTx{}. func (tapp *TestApp) RunCheckMsg(msg sdk.Msg) sdk.Result { - var tx = testTx{msg} + var tx = x.TestTx{msg} return tapp.RunCheckTx(tx) } // run tx through DeliverTx of TestApp -// NOTE: Skips authentication by wrapping msg in testTx{}. +// NOTE: Skips authentication by wrapping msg in TestTx{}. func (tapp *TestApp) RunDeliverMsg(msg sdk.Msg) sdk.Result { - var tx = testTx{msg} + var tx = x.TestTx{msg} return tapp.RunDeliverTx(tx) } @@ -102,20 +103,3 @@ func (tapp *TestApp) MultiStoreCheck() sdk.MultiStore { func (tapp *TestApp) MultiStoreDeliver() sdk.MultiStore { return tapp.BaseApp.msDeliver } - -//---------------------------------------- -// testTx - -type testTx struct { - sdk.Msg -} - -// nolint -func (tx testTx) GetMsg() sdk.Msg { return tx.Msg } -func (tx testTx) GetSigners() []crypto.Address { return nil } -func (tx testTx) GetFeePayer() crypto.Address { return nil } -func (tx testTx) GetSignatures() []sdk.StdSignature { return nil } -func IsTestAppTx(tx sdk.Tx) bool { - _, ok := tx.(testTx) - return ok -} diff --git a/baseapp/testapp/x/tx.go b/baseapp/testapp/x/tx.go new file mode 100644 index 000000000..d99e56049 --- /dev/null +++ b/baseapp/testapp/x/tx.go @@ -0,0 +1,22 @@ +package baseapp + +import ( + "github.com/tendermint/go-crypto" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// testing transaction +type TestTx struct { + sdk.Msg +} + +// nolint +func (tx TestTx) GetMsg() sdk.Msg { return tx.Msg } +func (tx TestTx) GetSigners() []crypto.Address { return nil } +func (tx TestTx) GetFeePayer() crypto.Address { return nil } +func (tx TestTx) GetSignatures() []sdk.StdSignature { return nil } +func IsTestAppTx(tx sdk.Tx) bool { + _, ok := tx.(TestTx) + return ok +} diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index ead962e12..b42002131 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -11,7 +11,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/sketchy" - abci "github.com/tendermint/abci/types" crypto "github.com/tendermint/go-crypto" "github.com/tendermint/go-wire" cmn "github.com/tendermint/tmlibs/common" @@ -27,27 +26,43 @@ type BasecoinApp struct { // keys to access the substores capKeyMainStore *sdk.KVStoreKey capKeyIBCStore *sdk.KVStoreKey + + // Manage getting and setting accounts + accountMapper sdk.AccountMapper } func NewBasecoinApp(genesisPath string) *BasecoinApp { - var app = &BasecoinApp{ - cdc: makeCodex(), - capKeyMainStore: sdk.NewKVStoreKey("main"), - capKeyIBCStore: sdk.NewKVStoreKey("ibc"), - } + // define some keys + mainKey := sdk.NewKVStoreKey("main") + ibcKey := sdk.NewKVStoreKey("ibc") - var accMapper = auth.NewAccountMapper( - app.capKeyMainStore, // target store + // define a mapper + accountMapper := auth.NewAccountMapper( + mainKey, // target store &types.AppAccount{}, // prototype ) + cdc := accountMapper.WireCodec() + auth.RegisterWireBaseAccount(cdc) + // Make accountMapper's WireCodec() inaccessible. + app.accountMapper = accountMapper.Seal() + + // create your application object + var app = &BasecoinApp{ + BaseApp: bam.NewBaseApp(appName, accountMapper), + cdc: makeTxCodec(), + capKeyMainStore: mainKey, + capKeyIBCStore: ibcKey, + } - app.BaseApp = bam.NewBaseAppExpanded(appName, accMapper) app.initBaseAppTxDecoder() app.initBaseAppInitStater(genesisPath) - // Add the handlers - app.Router().AddRoute("bank", bank.NewHandler(bank.NewCoinKeeper(app.AccountMapper()))) + app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore) + + // add handlers + app.SetAnteHandler(auth.NewAnteHandler(accountMapper)) + app.Router().AddRoute("bank", bank.NewHandler(bank.NewCoinKeeper(accountMapper))) app.Router().AddRoute("sketchy", sketchy.NewHandler()) // load the stores @@ -89,20 +104,11 @@ func (app *BasecoinApp) initBaseAppTxDecoder() { // define the custom logic for basecoin initialization func (app *BasecoinApp) initBaseAppInitStater(genesisPath string) { - genesisAppState, err := bam.ReadGenesisAppState(genesisPath) + genesisAppState, err := bam.LoadGenesisAppState(genesisPath) if err != nil { panic(fmt.Errorf("error loading genesis state: %v", err)) } - // set up the cache store for ctx, get ctx - // TODO: combine with InitChain and let tendermint invoke it. - app.BaseApp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{}}) - ctx := app.BaseApp.NewContext(false, nil) // context for DeliverTx - err = app.BaseApp.InitStater(ctx, genesisAppState) - if err != nil { - cmn.Exit(fmt.Sprintf("error initializing application genesis state: %v", err)) - } - app.BaseApp.SetInitStater(func(ctx sdk.Context, state json.RawMessage) sdk.Error { if state == nil { return nil @@ -119,7 +125,7 @@ func (app *BasecoinApp) initBaseAppInitStater(genesisPath string) { if err != nil { return sdk.ErrGenesisParse("").TraceCause(err, "") } - app.AccountMapper().SetAccount(ctx, acc) + app.accountMapper.SetAccount(ctx, acc) } return nil }) diff --git a/examples/basecoin/app/app_test.go b/examples/basecoin/app/app_test.go index 2014fef7c..83e6edbd0 100644 --- a/examples/basecoin/app/app_test.go +++ b/examples/basecoin/app/app_test.go @@ -26,7 +26,7 @@ func newTestBasecoinApp() *testBasecoinApp { tba := &testBasecoinApp{ BasecoinApp: app, } - tba.TestApp = bam.NewTestApp(app.BaseApp) + tba.TestApp = testapp.NewTestApp(app.BaseApp) return tba } diff --git a/x/auth/ante.go b/x/auth/ante.go index a91fa55c2..0c0012522 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -1,7 +1,7 @@ package auth import ( - bam "github.com/cosmos/cosmos-sdk/baseapp" + tax "github.com/cosmos/cosmos-sdk/baseapp/testapp/x" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -25,14 +25,14 @@ func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler { // TODO: accountMapper.SetAccount(ctx, payerAddr) } else { // TODO: Ensure that some other spam prevention is used. - // NOTE: bam.TestApp.RunDeliverMsg/RunCheckMsg will - // create a Tx with no payer. + // NOTE: testapp.TestApp.RunDeliverMsg/RunCheckMsg will + // create a Tx with no payer. } var sigs = tx.GetSignatures() // Assert that there are signatures. - if !bam.IsTestAppTx(tx) { + if !tax.IsTestAppTx(tx) { if len(sigs) == 0 { return ctx, sdk.ErrUnauthorized("no signers").Result(), @@ -46,7 +46,7 @@ func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler { var signerAccs = make([]sdk.Account, len(signerAddrs)) // Assert that number of signatures is correct. - if !bam.IsTestAppTx(tx) { + if !tax.IsTestAppTx(tx) { if len(sigs) != len(signerAddrs) { return ctx, sdk.ErrUnauthorized("wrong number of signers").Result(), From 938ee94e9e64fb478e7061d159fd9ef72d0f1b21 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 15 Feb 2018 14:35:46 +0000 Subject: [PATCH 06/14] WIP refactor working --- baseapp/baseapp.go | 4 ++++ baseapp/{testapp => }/testapp.go | 13 ++++++------- baseapp/{testapp/x => testtx}/tx.go | 2 +- examples/basecoin/app/app.go | 13 ++++++++++--- examples/basecoin/app/app_test.go | 2 +- x/auth/ante.go | 6 +++--- 6 files changed, 25 insertions(+), 15 deletions(-) rename baseapp/{testapp => }/testapp.go (91%) rename baseapp/{testapp/x => testtx}/tx.go (96%) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 63bf6f764..1c2a26bc9 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -196,6 +196,10 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC // TODO: Use req.Validators // TODO: Use req.AppState in InitStater + if app.InitStater == nil { + return + } + app.msDeliver = app.cms.CacheMultiStore() ctx := app.GenesisContext(nil) diff --git a/baseapp/testapp/testapp.go b/baseapp/testapp.go similarity index 91% rename from baseapp/testapp/testapp.go rename to baseapp/testapp.go index a80c494f4..024b08a5c 100644 --- a/baseapp/testapp/testapp.go +++ b/baseapp/testapp.go @@ -1,24 +1,23 @@ -package testapp +package baseapp import ( abci "github.com/tendermint/abci/types" - bam "github.com/cosmos/cosmos-sdk/baseapp" - x "github.com/cosmos/cosmos-sdk/baseapp/testapp/x" + "github.com/cosmos/cosmos-sdk/baseapp/testtx" sdk "github.com/cosmos/cosmos-sdk/types" ) // TestApp wraps BaseApp with helper methods, // and exposes more functionality than otherwise needed. type TestApp struct { - *bam.BaseApp + *BaseApp // These get set as we receive them. *abci.ResponseBeginBlock *abci.ResponseEndBlock } -func NewTestApp(bapp *bam.BaseApp) *TestApp { +func NewTestApp(bapp *BaseApp) *TestApp { app := &TestApp{ BaseApp: bapp, } @@ -78,14 +77,14 @@ func (tapp *TestApp) RunDeliverTx(tx sdk.Tx) sdk.Result { // run tx through CheckTx of TestApp // NOTE: Skips authentication by wrapping msg in TestTx{}. func (tapp *TestApp) RunCheckMsg(msg sdk.Msg) sdk.Result { - var tx = x.TestTx{msg} + var tx = testtx.TestTx{msg} return tapp.RunCheckTx(tx) } // run tx through DeliverTx of TestApp // NOTE: Skips authentication by wrapping msg in TestTx{}. func (tapp *TestApp) RunDeliverMsg(msg sdk.Msg) sdk.Result { - var tx = x.TestTx{msg} + var tx = testtx.TestTx{msg} return tapp.RunDeliverTx(tx) } diff --git a/baseapp/testapp/x/tx.go b/baseapp/testtx/tx.go similarity index 96% rename from baseapp/testapp/x/tx.go rename to baseapp/testtx/tx.go index d99e56049..0a8275114 100644 --- a/baseapp/testapp/x/tx.go +++ b/baseapp/testtx/tx.go @@ -1,4 +1,4 @@ -package baseapp +package testtx import ( "github.com/tendermint/go-crypto" diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index b42002131..3b02b8519 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -44,17 +44,18 @@ func NewBasecoinApp(genesisPath string) *BasecoinApp { ) cdc := accountMapper.WireCodec() auth.RegisterWireBaseAccount(cdc) - // Make accountMapper's WireCodec() inaccessible. - app.accountMapper = accountMapper.Seal() // create your application object var app = &BasecoinApp{ - BaseApp: bam.NewBaseApp(appName, accountMapper), + BaseApp: bam.NewBaseApp(appName), cdc: makeTxCodec(), capKeyMainStore: mainKey, capKeyIBCStore: ibcKey, } + // Make accountMapper's WireCodec() inaccessible. + app.accountMapper = accountMapper.Seal() + app.initBaseAppTxDecoder() app.initBaseAppInitStater(genesisPath) @@ -110,6 +111,12 @@ func (app *BasecoinApp) initBaseAppInitStater(genesisPath string) { } app.BaseApp.SetInitStater(func(ctx sdk.Context, state json.RawMessage) sdk.Error { + + // TODO use state ABCI + if state == nil { + state = genesisAppState + } + if state == nil { return nil } diff --git a/examples/basecoin/app/app_test.go b/examples/basecoin/app/app_test.go index 83e6edbd0..2014fef7c 100644 --- a/examples/basecoin/app/app_test.go +++ b/examples/basecoin/app/app_test.go @@ -26,7 +26,7 @@ func newTestBasecoinApp() *testBasecoinApp { tba := &testBasecoinApp{ BasecoinApp: app, } - tba.TestApp = testapp.NewTestApp(app.BaseApp) + tba.TestApp = bam.NewTestApp(app.BaseApp) return tba } diff --git a/x/auth/ante.go b/x/auth/ante.go index 0c0012522..0c66a9983 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -1,7 +1,7 @@ package auth import ( - tax "github.com/cosmos/cosmos-sdk/baseapp/testapp/x" + "github.com/cosmos/cosmos-sdk/baseapp/testtx" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -32,7 +32,7 @@ func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler { var sigs = tx.GetSignatures() // Assert that there are signatures. - if !tax.IsTestAppTx(tx) { + if !testtx.IsTestAppTx(tx) { if len(sigs) == 0 { return ctx, sdk.ErrUnauthorized("no signers").Result(), @@ -46,7 +46,7 @@ func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler { var signerAccs = make([]sdk.Account, len(signerAddrs)) // Assert that number of signatures is correct. - if !tax.IsTestAppTx(tx) { + if !testtx.IsTestAppTx(tx) { if len(sigs) != len(signerAddrs) { return ctx, sdk.ErrUnauthorized("wrong number of signers").Result(), From 1555c4876e15fe23712e241a6fe901a048b12244 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 15 Feb 2018 16:00:57 +0000 Subject: [PATCH 07/14] pretty good refactor --- examples/basecoin/app/app.go | 74 ++++++++++++++---------------------- x/auth/mapper.go | 9 +++-- 2 files changed, 33 insertions(+), 50 deletions(-) diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index 3b02b8519..feb034926 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -16,8 +16,6 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) -const appName = "BasecoinApp" - // Extended ABCI application type BasecoinApp struct { *bam.BaseApp @@ -33,63 +31,47 @@ type BasecoinApp struct { func NewBasecoinApp(genesisPath string) *BasecoinApp { - // define some keys - mainKey := sdk.NewKVStoreKey("main") - ibcKey := sdk.NewKVStoreKey("ibc") - - // define a mapper - accountMapper := auth.NewAccountMapper( - mainKey, // target store - &types.AppAccount{}, // prototype - ) - cdc := accountMapper.WireCodec() - auth.RegisterWireBaseAccount(cdc) - // create your application object var app = &BasecoinApp{ - BaseApp: bam.NewBaseApp(appName), - cdc: makeTxCodec(), - capKeyMainStore: mainKey, - capKeyIBCStore: ibcKey, + BaseApp: bam.NewBaseApp("BasecoinApp"), + cdc: MakeTxCodec(), + capKeyMainStore: sdk.NewKVStoreKey("main"), + capKeyIBCStore: sdk.NewKVStoreKey("ibc"), } - // Make accountMapper's WireCodec() inaccessible. - app.accountMapper = accountMapper.Seal() - - app.initBaseAppTxDecoder() - app.initBaseAppInitStater(genesisPath) - - app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore) + // define the accountMapper + app.accountMapper = auth.NewAccountMapperSealed( + app.capKeyMainStore, // target store + &types.AppAccount{}, // prototype + ) // add handlers - app.SetAnteHandler(auth.NewAnteHandler(accountMapper)) - app.Router().AddRoute("bank", bank.NewHandler(bank.NewCoinKeeper(accountMapper))) + app.Router().AddRoute("bank", bank.NewHandler(bank.NewCoinKeeper(app.accountMapper))) app.Router().AddRoute("sketchy", sketchy.NewHandler()) - // load the stores - if err := app.LoadLatestVersion(app.capKeyMainStore); err != nil { + // initialize BaseApp + app.SetTxDecoder() + app.SetInitStater(genesisPath) + app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore) + app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper)) + err := app.LoadLatestVersion(app.capKeyMainStore) + if err != nil { cmn.Exit(err.Error()) } return app } -// Wire requires registration of interfaces & concrete types. All -// interfaces to be encoded/decoded in a Msg must be registered -// here, along with all the concrete types that implement them. -func makeTxCodec() (cdc *wire.Codec) { - cdc = wire.NewCodec() - - // Register crypto.[PubKey,PrivKey,Signature] types. - crypto.RegisterWire(cdc) - - // Register bank.[SendMsg,IssueMsg] types. - bank.RegisterWire(cdc) - - return +// custom tx codec +func MakeTxCodec() *wire.Codec { + cdc := wire.NewCodec() + crypto.RegisterWire(cdc) // Register crypto.[PubKey,PrivKey,Signature] types. + bank.RegisterWire(cdc) // Register bank.[SendMsg,IssueMsg] types. + return cdc } -func (app *BasecoinApp) initBaseAppTxDecoder() { +// custom logic for transaction decoding +func (app *BasecoinApp) SetTxDecoder() { app.BaseApp.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) { var tx = sdk.StdTx{} // StdTx.Msg is an interface whose concrete @@ -102,9 +84,10 @@ func (app *BasecoinApp) initBaseAppTxDecoder() { }) } -// define the custom logic for basecoin initialization -func (app *BasecoinApp) initBaseAppInitStater(genesisPath string) { +// custom logic for basecoin initialization +func (app *BasecoinApp) SetInitStater(genesisPath string) { + // TODO remove, use state ABCI genesisAppState, err := bam.LoadGenesisAppState(genesisPath) if err != nil { panic(fmt.Errorf("error loading genesis state: %v", err)) @@ -116,7 +99,6 @@ func (app *BasecoinApp) initBaseAppInitStater(genesisPath string) { if state == nil { state = genesisAppState } - if state == nil { return nil } diff --git a/x/auth/mapper.go b/x/auth/mapper.go index fb69975f8..6cd51552c 100644 --- a/x/auth/mapper.go +++ b/x/auth/mapper.go @@ -36,8 +36,8 @@ func NewAccountMapper(key sdk.StoreKey, proto sdk.Account) accountMapper { } } -// XXX add comment -func NewAccountMapperSealed(key sdk.StoreKey, proto sdk.Account) accountMapper { +// Create and return a sealed account mapper +func NewAccountMapperSealed(key sdk.StoreKey, proto sdk.Account) sealedAccountMapper { cdc := wire.NewCodec() am := accountMapper{ key: key, @@ -45,8 +45,9 @@ func NewAccountMapperSealed(key sdk.StoreKey, proto sdk.Account) accountMapper { cdc: cdc, } RegisterWireBaseAccount(cdc) - am.Seal() - return am + + // make accountMapper's WireCodec() inaccessible, return + return am.Seal() } // Returns the go-wire codec. You may need to register interfaces From 1698e4e2d8580f12596024e8515dd45715d08923 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 16 Feb 2018 19:52:07 -0500 Subject: [PATCH 08/14] small test and some comments --- baseapp/baseapp_test.go | 31 ++++++++++++++++++++++++++++++- baseapp/router.go | 3 ++- types/store.go | 3 ++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index 695115729..3fad3d7de 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -16,6 +16,35 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +func TestMountStores(t *testing.T) { + app := NewBaseApp(t.Name()) + + // make some cap keys + capKey1 := sdk.NewKVStoreKey("key1") + capKey2 := sdk.NewKVStoreKey("key2") + + // no stores are mounted + assert.Panics(t, func() { app.LoadLatestVersion(capKey1) }) + + app.MountStoresIAVL(capKey1, capKey2) + + // both stores are mounted + err := app.LoadLatestVersion(capKey1) + assert.Nil(t, err) + err = app.LoadLatestVersion(capKey2) + assert.Nil(t, err) +} + +func TestLoadVersion(t *testing.T) { + // TODO +} + +func TestInitStater(t *testing.T) { + // TODO +} + +//---------------------- + // A mock transaction to update a validator's voting power. type testUpdatePowerTx struct { Addr []byte @@ -33,7 +62,7 @@ func (tx testUpdatePowerTx) GetSigners() []crypto.Address { return ni func (tx testUpdatePowerTx) GetFeePayer() crypto.Address { return nil } func (tx testUpdatePowerTx) GetSignatures() []sdk.StdSignature { return nil } -func TestBasic(t *testing.T) { +func TestExecution(t *testing.T) { // Create app. app := NewBaseApp(t.Name()) diff --git a/baseapp/router.go b/baseapp/router.go index 2f27d7a54..b6b56792b 100644 --- a/baseapp/router.go +++ b/baseapp/router.go @@ -6,12 +6,13 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// Router - TODO add description +// Router provides handlers for each transaction type. type Router interface { AddRoute(r string, h sdk.Handler) Route(path string) (h sdk.Handler) } +// map a transaction type to a handler type route struct { r string h sdk.Handler diff --git a/types/store.go b/types/store.go index 872c38090..b552f8cb0 100644 --- a/types/store.go +++ b/types/store.go @@ -61,7 +61,8 @@ type CommitMultiStore interface { Committer MultiStore - // Mount a store of type. + // Mount a store of type using the given db. + // If db == nil, the new store will use the CommitMultiStore db. MountStoreWithDB(key StoreKey, typ StoreType, db dbm.DB) // Panics on a nil key. From 96b734b729f7f483a4ccfedc5825f5f396c6edb0 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 16 Feb 2018 19:53:11 -0500 Subject: [PATCH 09/14] glide update for abci RequestInitChain.AppStateBytes --- glide.lock | 10 +++++----- glide.yaml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/glide.lock b/glide.lock index bb013ee71..341a27020 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 2b4ad3bf1489a7cb5e62c6cb4c1fa976d4ae21993743e4968418c4e81925fb99 -updated: 2018-02-13T08:33:22.402132782-05:00 +hash: 4d523b19f5b2f54caca37e196582c85d459fdfa5d5383d7e97ee81639b46129d +updated: 2018-02-16T19:52:42.711474619-05:00 imports: - name: github.com/btcsuite/btcd version: 50de9da05b50eb15658bb350f6ea24368a111ab7 @@ -82,7 +82,7 @@ imports: - name: github.com/spf13/viper version: 25b30aa063fc18e48662b86996252eabdcf2f0c7 - name: github.com/syndtr/goleveldb - version: 211f780988068502fe874c44dae530528ebd840f + version: 34011bf325bce385408353a30b101fe5e923eb6e subpackages: - leveldb - leveldb/cache @@ -97,7 +97,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: bf70f5e273bd7dd6e22e64186cd1ccc4e3a03df1 + version: a6be687088a7158e9e431931c3769d6706f90c4c subpackages: - server - types @@ -113,7 +113,7 @@ imports: - name: github.com/tendermint/iavl version: 1a59ec0c82dc940c25339dd7c834df5cb76a95cb - name: github.com/tendermint/tmlibs - version: c858b3ba78316fdd9096a11409a7e7a493e7d974 + version: a0f652dc2e131be86fc8d9e4e2beec9831a8a6ec subpackages: - cli - common diff --git a/glide.yaml b/glide.yaml index 276513b2c..b2d6a9477 100644 --- a/glide.yaml +++ b/glide.yaml @@ -8,7 +8,7 @@ import: version: ^0.8.0 - package: github.com/rigelrozanski/common - package: github.com/tendermint/abci - version: develop + version: feature/init-chain-app-state subpackages: - server - types From c7df77ce3ce2882a38023a7322d7603d1677c364 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 16 Feb 2018 20:15:38 -0500 Subject: [PATCH 10/14] simplify baseapp and InitStater -> InitChainer --- baseapp/baseapp.go | 85 ++++++++++++-------------------- baseapp/baseapp_test.go | 16 ++++++- baseapp/context.go | 36 -------------- baseapp/genesis.go | 30 ------------ baseapp/testapp.go | 104 ---------------------------------------- types/abci.go | 6 +++ types/genesis.go | 6 --- 7 files changed, 51 insertions(+), 232 deletions(-) delete mode 100644 baseapp/context.go delete mode 100644 baseapp/genesis.go delete mode 100644 baseapp/testapp.go create mode 100644 types/abci.go delete mode 100644 types/genesis.go diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 1c2a26bc9..793727a1b 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -1,9 +1,7 @@ package baseapp import ( - "bytes" "fmt" - "os" "runtime/debug" "github.com/golang/protobuf/proto" @@ -27,7 +25,7 @@ type BaseApp struct { db dbm.DB // common DB backend cms sdk.CommitMultiStore // Main (uncached) state txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx - InitStater sdk.InitStater // TODO unexpose + initChainer sdk.InitChainer // anteHandler sdk.AnteHandler // ante handler for fee and auth router Router // handle any kind of message @@ -43,34 +41,14 @@ type BaseApp struct { var _ abci.Application = &BaseApp{} // Create and name new BaseApp -func NewBaseApp(name string) *BaseApp { - var baseapp = &BaseApp{ - logger: makeDefaultLogger(), +func NewBaseApp(name string, logger log.Logger, db dbm.DB) *BaseApp { + return &BaseApp{ + logger: logger, name: name, - db: nil, - cms: nil, + db: db, + cms: store.NewCommitMultiStore(db), router: NewRouter(), } - baseapp.initDB() - baseapp.initMultiStore() - - return baseapp -} - -// Create the underlying leveldb datastore which will -// persist the Merkle tree inner & leaf nodes. -func (app *BaseApp) initDB() { - db, err := dbm.NewGoLevelDB(app.name, "data") - if err != nil { - fmt.Println(err) - os.Exit(1) - } - app.db = db -} - -func (app *BaseApp) initMultiStore() { - cms := store.NewCommitMultiStore(app.db) - app.cms = cms } // BaseApp Name @@ -94,8 +72,8 @@ func (app *BaseApp) MountStore(key sdk.StoreKey, typ sdk.StoreType) { func (app *BaseApp) SetTxDecoder(txDecoder sdk.TxDecoder) { app.txDecoder = txDecoder } -func (app *BaseApp) SetInitStater(initStater sdk.InitStater) { - app.InitStater = initStater +func (app *BaseApp) SetInitChainer(initChainer sdk.InitChainer) { + app.initChainer = initChainer } func (app *BaseApp) SetAnteHandler(ah sdk.AnteHandler) { // deducts fee from payer, verifies signatures and nonces, sets Signers to ctx. @@ -170,6 +148,22 @@ func (app *BaseApp) initFromStore(mainKey sdk.StoreKey) error { return nil } +// NewContext returns a new Context suitable for AnteHandler (and indirectly Handler) processing. +// NOTE: txBytes may be nil to support TestApp.RunCheckTx +// and TestApp.RunDeliverTx. +func (app *BaseApp) NewContext(isCheckTx bool, txBytes []byte) sdk.Context { + + store := app.getMultiStore(isCheckTx) + if store == nil { + panic("BaseApp.NewContext() requires BeginBlock(): missing store") + } + if app.header == nil { + panic("BaseApp.NewContext() requires BeginBlock(): missing header") + } + + return sdk.NewContext(store, *app.header, isCheckTx, txBytes) +} + //---------------------------------------- // ABCI @@ -193,18 +187,18 @@ func (app *BaseApp) SetOption(req abci.RequestSetOption) (res abci.ResponseSetOp // Implements ABCI func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) { - // TODO: Use req.Validators - // TODO: Use req.AppState in InitStater - - if app.InitStater == nil { + if app.initChainer == nil { + // TODO: should we have some default handling of validators? return } - app.msDeliver = app.cms.CacheMultiStore() - ctx := app.GenesisContext(nil) + // get the store and make a context for the initialization + store := app.cms.CacheMultiStore() + ctx := sdk.NewContext(store, abci.Header{}, false, nil) - err := app.InitStater(ctx, nil) + err := app.initChainer(ctx, req) if err != nil { + // TODO: something better https://github.com/cosmos/cosmos-sdk/issues/468 cmn.Exit(fmt.Sprintf("error initializing application genesis state: %v", err)) } return @@ -376,20 +370,3 @@ func (app *BaseApp) getMultiStore(isCheckTx bool) sdk.MultiStore { } return app.msDeliver } - -// Return index of list with validator of same PubKey, or -1 if no match -func pubKeyIndex(val *abci.Validator, list []*abci.Validator) int { - for i, v := range list { - if bytes.Equal(val.PubKey, v.PubKey) { - return i - } - } - return -1 -} - -// Make a simple default logger -// TODO: Make log capturable for each transaction, and return it in -// ResponseDeliverTx.Log and ResponseCheckTx.Log. -func makeDefaultLogger() log.Logger { - return log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") -} diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index 3fad3d7de..2c1cbd8bd 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "os" "testing" "github.com/stretchr/testify/assert" @@ -12,12 +13,23 @@ import ( "github.com/tendermint/go-crypto" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" + "github.com/tendermint/tmlibs/log" sdk "github.com/cosmos/cosmos-sdk/types" ) +func defaultLogger() log.Logger { + return log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") +} + +func newBaseApp(name string) *BaseApp { + logger := defaultLogger() + db := dbm.NewMemDB() + return NewBaseApp(name, logger, db) +} + func TestMountStores(t *testing.T) { - app := NewBaseApp(t.Name()) + app := newBaseApp(t.Name()) // make some cap keys capKey1 := sdk.NewKVStoreKey("key1") @@ -65,7 +77,7 @@ func (tx testUpdatePowerTx) GetSignatures() []sdk.StdSignature { return ni func TestExecution(t *testing.T) { // Create app. - app := NewBaseApp(t.Name()) + app := newBaseApp(t.Name()) storeKeys := createMounts(app.cms) app.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) { var ttx testUpdatePowerTx diff --git a/baseapp/context.go b/baseapp/context.go deleted file mode 100644 index 8ac10bce7..000000000 --- a/baseapp/context.go +++ /dev/null @@ -1,36 +0,0 @@ -package baseapp - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - abci "github.com/tendermint/abci/types" -) - -// NewContext returns a new Context suitable for AnteHandler (and indirectly Handler) processing. -// NOTE: txBytes may be nil to support TestApp.RunCheckTx -// and TestApp.RunDeliverTx. -func (app *BaseApp) NewContext(isCheckTx bool, txBytes []byte) sdk.Context { - var store sdk.MultiStore - if isCheckTx { - store = app.msCheck - } else { - store = app.msDeliver - } - - if store == nil { - panic("BaseApp.NewContext() requires BeginBlock(): missing store") - } - if app.header == nil { - panic("BaseApp.NewContext() requires BeginBlock(): missing header") - } - - return sdk.NewContext(store, *app.header, isCheckTx, txBytes) -} - -// context used during genesis -func (app *BaseApp) GenesisContext(txBytes []byte) sdk.Context { - store := app.msDeliver - if store == nil { - panic("BaseApp.NewContext() requires BeginBlock(): missing store") - } - return sdk.NewContext(store, abci.Header{}, false, txBytes) -} diff --git a/baseapp/genesis.go b/baseapp/genesis.go deleted file mode 100644 index acd7d7688..000000000 --- a/baseapp/genesis.go +++ /dev/null @@ -1,30 +0,0 @@ -package baseapp - -import ( - "encoding/json" - "io/ioutil" -) - -// TODO: remove from here and pass the AppState through InitChain - -// GenesisDoc defines the initial conditions for a tendermint blockchain, in particular its validator set. -type GenesisDoc struct { - AppState json.RawMessage `json:"app_state,omitempty"` -} - -// GenesisDocFromFile reads JSON data from a file and unmarshalls it into a GenesisDoc. -func LoadGenesisAppState(genesisPath string) (state json.RawMessage, err error) { - if genesisPath == "" { - return - } - jsonBlob, err := ioutil.ReadFile(genesisPath) - if err != nil { - return nil, err - } - genDoc := GenesisDoc{} - err = json.Unmarshal(jsonBlob, &genDoc) - if err != nil { - return nil, err - } - return genDoc.AppState, nil -} diff --git a/baseapp/testapp.go b/baseapp/testapp.go deleted file mode 100644 index 024b08a5c..000000000 --- a/baseapp/testapp.go +++ /dev/null @@ -1,104 +0,0 @@ -package baseapp - -import ( - abci "github.com/tendermint/abci/types" - - "github.com/cosmos/cosmos-sdk/baseapp/testtx" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// TestApp wraps BaseApp with helper methods, -// and exposes more functionality than otherwise needed. -type TestApp struct { - *BaseApp - - // These get set as we receive them. - *abci.ResponseBeginBlock - *abci.ResponseEndBlock -} - -func NewTestApp(bapp *BaseApp) *TestApp { - app := &TestApp{ - BaseApp: bapp, - } - return app -} - -// execute BaseApp BeginBlock -func (tapp *TestApp) RunBeginBlock() { - if tapp.header != nil { - panic("TestApp.header not nil, BeginBlock already run, or EndBlock not yet run.") - } - cms := tapp.CommitMultiStore() - lastCommit := cms.LastCommitID() - header := abci.Header{ - ChainID: "chain_" + tapp.BaseApp.name, - Height: lastCommit.Version + 1, - Time: -1, // TODO - NumTxs: -1, // TODO - LastCommitHash: lastCommit.Hash, - DataHash: nil, // TODO - ValidatorsHash: nil, // TODO - AppHash: nil, // TODO - } - res := tapp.BeginBlock(abci.RequestBeginBlock{ - Hash: nil, // TODO - Header: header, - AbsentValidators: nil, // TODO - ByzantineValidators: nil, // TODO - }) - tapp.ResponseBeginBlock = &res - return -} - -// kill resources used by basecapp -func (tapp *TestApp) Close() { - tapp.db.Close() -} - -func (tapp *TestApp) ensureBeginBlock() { - if tapp.header == nil { - panic("TestApp.header was nil, call TestApp.RunBeginBlock()") - } -} - -// run tx through CheckTx of TestApp -func (tapp *TestApp) RunCheckTx(tx sdk.Tx) sdk.Result { - tapp.ensureBeginBlock() - return tapp.BaseApp.runTx(true, nil, tx) -} - -// run tx through DeliverTx of TestApp -func (tapp *TestApp) RunDeliverTx(tx sdk.Tx) sdk.Result { - tapp.ensureBeginBlock() - return tapp.BaseApp.runTx(false, nil, tx) -} - -// run tx through CheckTx of TestApp -// NOTE: Skips authentication by wrapping msg in TestTx{}. -func (tapp *TestApp) RunCheckMsg(msg sdk.Msg) sdk.Result { - var tx = testtx.TestTx{msg} - return tapp.RunCheckTx(tx) -} - -// run tx through DeliverTx of TestApp -// NOTE: Skips authentication by wrapping msg in TestTx{}. -func (tapp *TestApp) RunDeliverMsg(msg sdk.Msg) sdk.Result { - var tx = testtx.TestTx{msg} - return tapp.RunDeliverTx(tx) -} - -// return the commited multistore -func (tapp *TestApp) CommitMultiStore() sdk.CommitMultiStore { - return tapp.BaseApp.cms -} - -// return a cache-wrap CheckTx state of multistore -func (tapp *TestApp) MultiStoreCheck() sdk.MultiStore { - return tapp.BaseApp.msCheck -} - -// return a cache-wrap DeliverTx state of multistore -func (tapp *TestApp) MultiStoreDeliver() sdk.MultiStore { - return tapp.BaseApp.msDeliver -} diff --git a/types/abci.go b/types/abci.go new file mode 100644 index 000000000..58f40dd67 --- /dev/null +++ b/types/abci.go @@ -0,0 +1,6 @@ +package types + +import abci "github.com/tendermint/abci/types" + +// initialize application state at genesis +type InitChainer func(ctx Context, req abci.RequestInitChain) Error diff --git a/types/genesis.go b/types/genesis.go deleted file mode 100644 index 643235e3e..000000000 --- a/types/genesis.go +++ /dev/null @@ -1,6 +0,0 @@ -package types - -import "encoding/json" - -// function variable used to initialize application state at genesis -type InitStater func(ctx Context, state json.RawMessage) Error From f6cea66e2ea9bfd8fe34b08fb4343626f1ec8a34 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 16 Feb 2018 20:58:51 -0500 Subject: [PATCH 11/14] test and fix InitChain --- baseapp/baseapp.go | 13 ++++++++++--- baseapp/baseapp_test.go | 39 ++++++++++++++++++++++++++++++++++++--- store/iavlstore.go | 1 - 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 793727a1b..1dc63c15e 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -186,21 +186,28 @@ func (app *BaseApp) SetOption(req abci.RequestSetOption) (res abci.ResponseSetOp } // Implements ABCI +// InitChain runs the initialization logic directly on the CommitMultiStore and commits it. func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) { if app.initChainer == nil { // TODO: should we have some default handling of validators? return } - // get the store and make a context for the initialization - store := app.cms.CacheMultiStore() - ctx := sdk.NewContext(store, abci.Header{}, false, nil) + // make a context for the initialization. + // NOTE: we're writing to the cms directly, without a CacheWrap + ctx := sdk.NewContext(app.cms, abci.Header{}, false, nil) err := app.initChainer(ctx, req) if err != nil { // TODO: something better https://github.com/cosmos/cosmos-sdk/issues/468 cmn.Exit(fmt.Sprintf("error initializing application genesis state: %v", err)) } + + // XXX this commits everything and bumps the version. + // With this, block 1 executes against state with version 1, but results in state with version 2. + // Is that what we want ? + app.cms.Commit() + return } diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index 2c1cbd8bd..fb136904c 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -29,7 +29,9 @@ func newBaseApp(name string) *BaseApp { } func TestMountStores(t *testing.T) { - app := newBaseApp(t.Name()) + name := t.Name() + app := newBaseApp(name) + assert.Equal(t, name, app.Name()) // make some cap keys capKey1 := sdk.NewKVStoreKey("key1") @@ -51,8 +53,39 @@ func TestLoadVersion(t *testing.T) { // TODO } -func TestInitStater(t *testing.T) { - // TODO +func TestInitChainer(t *testing.T) { + app := newBaseApp(t.Name()) + + // make a cap key and mount the store + capKey := sdk.NewKVStoreKey("main") + app.MountStoresIAVL(capKey) + err := app.LoadLatestVersion(capKey) // needed to make stores non-nil + assert.Nil(t, err) + + key, value := []byte("hello"), []byte("goodbye") + + // initChainer sets a value in the store + var initChainer sdk.InitChainer = func(ctx sdk.Context, req abci.RequestInitChain) sdk.Error { + store := ctx.KVStore(capKey) + store.Set(key, value) + return nil + } + + query := abci.RequestQuery{ + Path: "/main/key", + Data: key, + } + + // initChainer is nil - nothing happens + app.InitChain(abci.RequestInitChain{}) + res := app.Query(query) + assert.Equal(t, 0, len(res.Value)) + + // set initChainer and try again - should see the value + app.SetInitChainer(initChainer) + app.InitChain(abci.RequestInitChain{}) + res = app.Query(query) + assert.Equal(t, value, res.Value) } //---------------------- diff --git a/store/iavlstore.go b/store/iavlstore.go index 52deef367..e63585a16 100644 --- a/store/iavlstore.go +++ b/store/iavlstore.go @@ -19,7 +19,6 @@ const ( func LoadIAVLStore(db dbm.DB, id CommitID) (CommitStore, error) { tree := iavl.NewVersionedTree(db, defaultIAVLCacheSize) - fmt.Println("LoadIAVLStore Version ", id.Version) err := tree.LoadVersion(id.Version) if err != nil { return nil, err From c56b6254defaa85ded3e7dd27e833a97cf15bcf1 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 16 Feb 2018 21:13:35 -0500 Subject: [PATCH 12/14] update basecoin for baseapp changes - still need to fix tests --- examples/basecoin/app/app.go | 45 ++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index feb034926..d5544a023 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -3,6 +3,7 @@ package app import ( "encoding/json" "fmt" + "os" bam "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/examples/basecoin/types" @@ -11,9 +12,16 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/sketchy" + abci "github.com/tendermint/abci/types" crypto "github.com/tendermint/go-crypto" "github.com/tendermint/go-wire" cmn "github.com/tendermint/tmlibs/common" + dbm "github.com/tendermint/tmlibs/db" + "github.com/tendermint/tmlibs/log" +) + +const ( + appName = "BasecoinApp" ) // Extended ABCI application @@ -29,11 +37,18 @@ type BasecoinApp struct { accountMapper sdk.AccountMapper } -func NewBasecoinApp(genesisPath string) *BasecoinApp { +func NewBasecoinApp() *BasecoinApp { + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") + db, err := dbm.NewGoLevelDB(appName, "data") + if err != nil { + // TODO: better + fmt.Println(err) + os.Exit(1) + } // create your application object var app = &BasecoinApp{ - BaseApp: bam.NewBaseApp("BasecoinApp"), + BaseApp: bam.NewBaseApp(appName, logger, db), cdc: MakeTxCodec(), capKeyMainStore: sdk.NewKVStoreKey("main"), capKeyIBCStore: sdk.NewKVStoreKey("ibc"), @@ -51,10 +66,10 @@ func NewBasecoinApp(genesisPath string) *BasecoinApp { // initialize BaseApp app.SetTxDecoder() - app.SetInitStater(genesisPath) + app.SetInitChainer() app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore) app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper)) - err := app.LoadLatestVersion(app.capKeyMainStore) + err = app.LoadLatestVersion(app.capKeyMainStore) if err != nil { cmn.Exit(err.Error()) } @@ -85,26 +100,12 @@ func (app *BasecoinApp) SetTxDecoder() { } // custom logic for basecoin initialization -func (app *BasecoinApp) SetInitStater(genesisPath string) { - - // TODO remove, use state ABCI - genesisAppState, err := bam.LoadGenesisAppState(genesisPath) - if err != nil { - panic(fmt.Errorf("error loading genesis state: %v", err)) - } - - app.BaseApp.SetInitStater(func(ctx sdk.Context, state json.RawMessage) sdk.Error { - - // TODO use state ABCI - if state == nil { - state = genesisAppState - } - if state == nil { - return nil - } +func (app *BasecoinApp) SetInitChainer() { + app.BaseApp.SetInitChainer(func(ctx sdk.Context, req abci.RequestInitChain) sdk.Error { + stateJSON := req.AppStateBytes genesisState := new(types.GenesisState) - err := json.Unmarshal(state, genesisState) + err := json.Unmarshal(stateJSON, genesisState) if err != nil { return sdk.ErrGenesisParse("").TraceCause(err, "") } From c31f871de655660971a8119ad502a1791ab0d512 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 17 Feb 2018 16:19:34 -0500 Subject: [PATCH 13/14] finish removing TestApp and TestTx --- baseapp/baseapp.go | 54 +++++++-------- baseapp/testtx/tx.go | 22 ------ examples/basecoin/app/app.go | 17 ++--- examples/basecoin/app/app_test.go | 60 ++++++++--------- examples/basecoin/cmd/basecoind/main.go | 16 ++++- examples/dummy/main.go | 12 +++- types/tx_msg.go | 12 +++- x/auth/ante.go | 89 ++++++++++++------------- 8 files changed, 138 insertions(+), 144 deletions(-) delete mode 100644 baseapp/testtx/tx.go diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 1dc63c15e..f455b3184 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -31,10 +31,14 @@ type BaseApp struct { //-------------------- // Volatile + // .msCheck and .header are set on initialization. + // .msDeliver is only set (and reset) in BeginBlock. + // .header and .valUpdates are also reset in BeginBlock. + // .msCheck is only reset in Commit. + header abci.Header // current block header msCheck sdk.CacheMultiStore // CheckTx state, a cache-wrap of `.cms` msDeliver sdk.CacheMultiStore // DeliverTx state, a cache-wrap of `.cms` - header *abci.Header // current block header valUpdates []abci.Validator // cached validator changes from DeliverTx } @@ -114,7 +118,7 @@ func (app *BaseApp) LastBlockHeight() int64 { func (app *BaseApp) initFromStore(mainKey sdk.StoreKey) error { var lastCommitID = app.cms.LastCommitID() var main = app.cms.GetKVStore(mainKey) - var header *abci.Header + var header abci.Header // main store should exist. if main == nil { @@ -128,7 +132,7 @@ func (app *BaseApp) initFromStore(mainKey sdk.StoreKey) error { errStr := fmt.Sprintf("Version > 0 but missing key %s", mainHeaderKey) return errors.New(errStr) } - err := proto.Unmarshal(headerBytes, header) + err := proto.Unmarshal(headerBytes, &header) if err != nil { return errors.Wrap(err, "Failed to parse Header") } @@ -141,27 +145,21 @@ func (app *BaseApp) initFromStore(mainKey sdk.StoreKey) error { // set BaseApp state app.header = header - app.msCheck = nil + app.msCheck = app.cms.CacheMultiStore() app.msDeliver = nil app.valUpdates = nil return nil } -// NewContext returns a new Context suitable for AnteHandler (and indirectly Handler) processing. -// NOTE: txBytes may be nil to support TestApp.RunCheckTx -// and TestApp.RunDeliverTx. +// NewContext returns a new Context suitable for AnteHandler and Handler processing. +// NOTE: header is empty for checkTx +// NOTE: txBytes may be nil, for instance in tests (using app.Check or app.Deliver directly). func (app *BaseApp) NewContext(isCheckTx bool, txBytes []byte) sdk.Context { - store := app.getMultiStore(isCheckTx) - if store == nil { - panic("BaseApp.NewContext() requires BeginBlock(): missing store") - } - if app.header == nil { - panic("BaseApp.NewContext() requires BeginBlock(): missing header") - } - - return sdk.NewContext(store, *app.header, isCheckTx, txBytes) + // XXX CheckTx can't safely get the header + header := abci.Header{} + return sdk.NewContext(store, header, isCheckTx, txBytes) } //---------------------------------------- @@ -204,8 +202,7 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC } // XXX this commits everything and bumps the version. - // With this, block 1 executes against state with version 1, but results in state with version 2. - // Is that what we want ? + // https://github.com/cosmos/cosmos-sdk/issues/442#issuecomment-366470148 app.cms.Commit() return @@ -225,9 +222,8 @@ func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) { // Implements ABCI func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { // NOTE: For consistency we should unset these upon EndBlock. - app.header = &req.Header + app.header = req.Header app.msDeliver = app.cms.CacheMultiStore() - app.msCheck = app.cms.CacheMultiStore() app.valUpdates = nil return } @@ -255,7 +251,6 @@ func (app *BaseApp) CheckTx(txBytes []byte) (res abci.ResponseCheckTx) { }, Tags: result.Tags, } - } // Implements ABCI @@ -290,9 +285,16 @@ func (app *BaseApp) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) { } } -// txBytes may be nil in some cases, for example, when tx is -// coming from TestApp. Also, in the future we may support -// "internal" transactions. +// Mostly for testing +func (app *BaseApp) Check(tx sdk.Tx) (result sdk.Result) { + return app.runTx(true, nil, tx) +} +func (app *BaseApp) Deliver(tx sdk.Tx) (result sdk.Result) { + return app.runTx(false, nil, tx) +} + +// txBytes may be nil in some cases, eg. in tests. +// Also, in the future we may support "internal" transactions. func (app *BaseApp) runTx(isCheckTx bool, txBytes []byte, tx sdk.Tx) (result sdk.Result) { // Handle any panics. @@ -330,7 +332,7 @@ func (app *BaseApp) runTx(isCheckTx bool, txBytes []byte, tx sdk.Tx) (result sdk } // CacheWrap app.msDeliver in case it fails. - msCache := app.getMultiStore(isCheckTx).CacheMultiStore() + msCache := app.getMultiStore(false).CacheMultiStore() ctx = ctx.WithMultiStore(msCache) // Match and run route. @@ -350,9 +352,7 @@ func (app *BaseApp) runTx(isCheckTx bool, txBytes []byte, tx sdk.Tx) (result sdk func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) { res.ValidatorUpdates = app.valUpdates app.valUpdates = nil - app.header = nil app.msDeliver = nil - app.msCheck = nil return } diff --git a/baseapp/testtx/tx.go b/baseapp/testtx/tx.go deleted file mode 100644 index 0a8275114..000000000 --- a/baseapp/testtx/tx.go +++ /dev/null @@ -1,22 +0,0 @@ -package testtx - -import ( - "github.com/tendermint/go-crypto" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// testing transaction -type TestTx struct { - sdk.Msg -} - -// nolint -func (tx TestTx) GetMsg() sdk.Msg { return tx.Msg } -func (tx TestTx) GetSigners() []crypto.Address { return nil } -func (tx TestTx) GetFeePayer() crypto.Address { return nil } -func (tx TestTx) GetSignatures() []sdk.StdSignature { return nil } -func IsTestAppTx(tx sdk.Tx) bool { - _, ok := tx.(TestTx) - return ok -} diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index d5544a023..933268571 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -2,8 +2,6 @@ package app import ( "encoding/json" - "fmt" - "os" bam "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/examples/basecoin/types" @@ -37,15 +35,7 @@ type BasecoinApp struct { accountMapper sdk.AccountMapper } -func NewBasecoinApp() *BasecoinApp { - logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") - db, err := dbm.NewGoLevelDB(appName, "data") - if err != nil { - // TODO: better - fmt.Println(err) - os.Exit(1) - } - +func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp { // create your application object var app = &BasecoinApp{ BaseApp: bam.NewBaseApp(appName, logger, db), @@ -61,7 +51,8 @@ func NewBasecoinApp() *BasecoinApp { ) // add handlers - app.Router().AddRoute("bank", bank.NewHandler(bank.NewCoinKeeper(app.accountMapper))) + coinKeeper := bank.NewCoinKeeper(app.accountMapper) + app.Router().AddRoute("bank", bank.NewHandler(coinKeeper)) app.Router().AddRoute("sketchy", sketchy.NewHandler()) // initialize BaseApp @@ -69,7 +60,7 @@ func NewBasecoinApp() *BasecoinApp { app.SetInitChainer() app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore) app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper)) - err = app.LoadLatestVersion(app.capKeyMainStore) + err := app.LoadLatestVersion(app.capKeyMainStore) if err != nil { cmn.Exit(err.Error()) } diff --git a/examples/basecoin/app/app_test.go b/examples/basecoin/app/app_test.go index 2014fef7c..5ef1195c8 100644 --- a/examples/basecoin/app/app_test.go +++ b/examples/basecoin/app/app_test.go @@ -2,38 +2,31 @@ package app import ( "encoding/json" + "os" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - bam "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/examples/basecoin/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/bank" + abci "github.com/tendermint/abci/types" crypto "github.com/tendermint/go-crypto" + dbm "github.com/tendermint/tmlibs/db" + "github.com/tendermint/tmlibs/log" ) -type testBasecoinApp struct { - *BasecoinApp - *bam.TestApp -} - -func newTestBasecoinApp() *testBasecoinApp { - app := NewBasecoinApp("") - tba := &testBasecoinApp{ - BasecoinApp: app, - } - tba.TestApp = bam.NewTestApp(app.BaseApp) - return tba +func newBasecoinApp() *BasecoinApp { + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") + db := dbm.NewMemDB() + return NewBasecoinApp(logger, db) } func TestSendMsg(t *testing.T) { - tba := newTestBasecoinApp() - tba.RunBeginBlock() - defer tba.Close() + bapp := newBasecoinApp() // Construct a SendMsg. var msg = bank.SendMsg{ @@ -52,19 +45,25 @@ func TestSendMsg(t *testing.T) { }, } - // Run a Check on SendMsg. - res := tba.RunCheckMsg(msg) - assert.Equal(t, sdk.CodeOK, res.Code, res.Log) + priv := crypto.GenPrivKeyEd25519() + sig := priv.Sign(msg.GetSignBytes()) + tx := sdk.NewStdTx(msg, []sdk.StdSignature{{ + PubKey: priv.PubKey(), + Signature: sig, + }}) - // Run a Deliver on SendMsg. - res = tba.RunDeliverMsg(msg) + // Run a Check + res := bapp.Check(tx) + assert.Equal(t, sdk.CodeUnrecognizedAddress, res.Code, res.Log) + + // Simulate a Block + bapp.BeginBlock(abci.RequestBeginBlock{}) + res = bapp.Deliver(tx) assert.Equal(t, sdk.CodeUnrecognizedAddress, res.Code, res.Log) } func TestGenesis(t *testing.T) { - tba := newTestBasecoinApp() - tba.RunBeginBlock() - defer tba.Close() + bapp := newBasecoinApp() // construct some genesis bytes to reflect basecoin/types/AppAccount pk := crypto.GenPrivKeyEd25519().PubKey() @@ -82,13 +81,14 @@ func TestGenesis(t *testing.T) { types.NewGenesisAccount(acc), }, } - bytes, err := json.MarshalIndent(genesisState, "", "\t") + stateBytes, err := json.MarshalIndent(genesisState, "", "\t") - app := tba.BasecoinApp - ctx := app.BaseApp.NewContext(false, nil) // context for DeliverTx - err = app.BaseApp.InitStater(ctx, bytes) - require.Nil(t, err) + vals := []abci.Validator{} + bapp.InitChain(abci.RequestInitChain{vals, stateBytes}) - res1 := app.accountMapper.GetAccount(ctx, baseAcc.Address) + // a checkTx context + ctx := bapp.BaseApp.NewContext(true, nil) + + res1 := bapp.accountMapper.GetAccount(ctx, baseAcc.Address) assert.Equal(t, acc, res1) } diff --git a/examples/basecoin/cmd/basecoind/main.go b/examples/basecoin/cmd/basecoind/main.go index dff41d0b8..5ea25c42f 100644 --- a/examples/basecoin/cmd/basecoind/main.go +++ b/examples/basecoin/cmd/basecoind/main.go @@ -1,6 +1,12 @@ package main import ( + "fmt" + "os" + + dbm "github.com/tendermint/tmlibs/db" + "github.com/tendermint/tmlibs/log" + "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/examples/basecoin/app" ) @@ -8,6 +14,14 @@ import ( func main() { // TODO CREATE CLI - bapp := app.NewBasecoinApp("") + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "main") + + db, err := dbm.NewGoLevelDB("basecoind", "data") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + bapp := app.NewBasecoinApp(logger, db) baseapp.RunForever(bapp) } diff --git a/examples/dummy/main.go b/examples/dummy/main.go index 6457fb28c..b09662f1d 100644 --- a/examples/dummy/main.go +++ b/examples/dummy/main.go @@ -6,6 +6,8 @@ import ( "github.com/tendermint/abci/server" cmn "github.com/tendermint/tmlibs/common" + dbm "github.com/tendermint/tmlibs/db" + "github.com/tendermint/tmlibs/log" bam "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" @@ -13,11 +15,19 @@ import ( func main() { + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "main") + + db, err := dbm.NewGoLevelDB("basecoind", "data") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + // Capabilities key to access the main KVStore. var capKeyMainStore = sdk.NewKVStoreKey("main") // Create BaseApp. - var baseApp = bam.NewBaseApp("dummy") + var baseApp = bam.NewBaseApp("dummy", logger, db) // Set mounts for BaseApp's MultiStore. baseApp.MountStore(capKeyMainStore, sdk.StoreTypeIAVL) diff --git a/types/tx_msg.go b/types/tx_msg.go index ebed8a25a..8763075b8 100644 --- a/types/tx_msg.go +++ b/types/tx_msg.go @@ -49,15 +49,23 @@ type Tx interface { var _ Tx = (*StdTx)(nil) -// standard transaction form +// StdTx is a standard way to wrap a Msg with Signatures. +// NOTE: the first signature is the FeePayer (Signatures must not be nil). type StdTx struct { Msg Signatures []StdSignature } +func NewStdTx(msg Msg, sigs []StdSignature) StdTx { + return StdTx{ + Msg: msg, + Signatures: sigs, + } +} + //nolint func (tx StdTx) GetMsg() Msg { return tx.Msg } -func (tx StdTx) GetFeePayer() crypto.Address { return tx.Signatures[0].PubKey.Address() } +func (tx StdTx) GetFeePayer() crypto.Address { return tx.Signatures[0].PubKey.Address() } // XXX but PubKey is optional! func (tx StdTx) GetSignatures() []StdSignature { return tx.Signatures } //------------------------------------- diff --git a/x/auth/ante.go b/x/auth/ante.go index 0c66a9983..28785c809 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -1,7 +1,6 @@ package auth import ( - "github.com/cosmos/cosmos-sdk/baseapp/testtx" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -25,19 +24,15 @@ func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler { // TODO: accountMapper.SetAccount(ctx, payerAddr) } else { // TODO: Ensure that some other spam prevention is used. - // NOTE: testapp.TestApp.RunDeliverMsg/RunCheckMsg will - // create a Tx with no payer. } var sigs = tx.GetSignatures() // Assert that there are signatures. - if !testtx.IsTestAppTx(tx) { - if len(sigs) == 0 { - return ctx, - sdk.ErrUnauthorized("no signers").Result(), - true - } + if len(sigs) == 0 { + return ctx, + sdk.ErrUnauthorized("no signers").Result(), + true } // Ensure that sigs are correct. @@ -46,49 +41,47 @@ func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler { var signerAccs = make([]sdk.Account, len(signerAddrs)) // Assert that number of signatures is correct. - if !testtx.IsTestAppTx(tx) { - if len(sigs) != len(signerAddrs) { + if len(sigs) != len(signerAddrs) { + return ctx, + sdk.ErrUnauthorized("wrong number of signers").Result(), + true + } + + // Check each nonce and sig. + // TODO Refactor out. + for i, sig := range sigs { + + var signerAcc = accountMapper.GetAccount(ctx, signerAddrs[i]) + signerAccs[i] = signerAcc + + // If no pubkey, set pubkey. + if signerAcc.GetPubKey() == nil { + err := signerAcc.SetPubKey(sig.PubKey) + if err != nil { + return ctx, + sdk.ErrInternal("setting PubKey on signer").Result(), + true + } + } + + // Check and increment sequence number. + seq := signerAcc.GetSequence() + if seq != sig.Sequence { return ctx, - sdk.ErrUnauthorized("wrong number of signers").Result(), + sdk.ErrInvalidSequence("").Result(), + true + } + signerAcc.SetSequence(seq + 1) + + // Check sig. + if !sig.PubKey.VerifyBytes(msg.GetSignBytes(), sig.Signature) { + return ctx, + sdk.ErrUnauthorized("").Result(), true } - // Check each nonce and sig. - // TODO Refactor out. - for i, sig := range sigs { - - var signerAcc = accountMapper.GetAccount(ctx, signerAddrs[i]) - signerAccs[i] = signerAcc - - // If no pubkey, set pubkey. - if signerAcc.GetPubKey() == nil { - err := signerAcc.SetPubKey(sig.PubKey) - if err != nil { - return ctx, - sdk.ErrInternal("setting PubKey on signer").Result(), - true - } - } - - // Check and increment sequence number. - seq := signerAcc.GetSequence() - if seq != sig.Sequence { - return ctx, - sdk.ErrInvalidSequence("").Result(), - true - } - signerAcc.SetSequence(seq + 1) - - // Check sig. - if !sig.PubKey.VerifyBytes(msg.GetSignBytes(), sig.Signature) { - return ctx, - sdk.ErrUnauthorized("").Result(), - true - } - - // Save the account. - accountMapper.SetAccount(ctx, signerAcc) - } + // Save the account. + accountMapper.SetAccount(ctx, signerAcc) } ctx = WithSigners(ctx, signerAccs) From 8d8f4114a80e578cd03646072051bc43e1f0e926 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 17 Feb 2018 16:31:49 -0500 Subject: [PATCH 14/14] x/sketchy -> examples/basecoin/x/sketchy --- examples/basecoin/app/app.go | 15 ++++++++------- {x => examples/basecoin/x}/sketchy/handler.go | 0 2 files changed, 8 insertions(+), 7 deletions(-) rename {x => examples/basecoin/x}/sketchy/handler.go (100%) diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index 933268571..b1f66009e 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -3,19 +3,20 @@ package app import ( "encoding/json" - bam "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/examples/basecoin/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/bank" - "github.com/cosmos/cosmos-sdk/x/sketchy" - abci "github.com/tendermint/abci/types" crypto "github.com/tendermint/go-crypto" "github.com/tendermint/go-wire" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" "github.com/tendermint/tmlibs/log" + + bam "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/bank" + + "github.com/cosmos/cosmos-sdk/examples/basecoin/types" + "github.com/cosmos/cosmos-sdk/examples/basecoin/x/sketchy" ) const ( diff --git a/x/sketchy/handler.go b/examples/basecoin/x/sketchy/handler.go similarity index 100% rename from x/sketchy/handler.go rename to examples/basecoin/x/sketchy/handler.go