diff --git a/Makefile b/Makefile index 70068a9d8..703a0803e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -PACKAGES=$(shell go list ./... | grep -v '/vendor/' | grep -v '_attic') +PACKAGES=$(shell go list ./... | grep -v '/vendor/') BUILD_FLAGS = -ldflags "-X github.com/cosmos/cosmos-sdk/version.GitCommit=`git rev-parse --short HEAD`" -all: check_tools get_vendor_deps build test +all: check_tools get_vendor_deps build test ######################################## ### CI diff --git a/examples/basecoin/Makefile b/examples/basecoin/Makefile index 40eb03a26..aa45d0d83 100644 --- a/examples/basecoin/Makefile +++ b/examples/basecoin/Makefile @@ -1,7 +1,7 @@ -PACKAGES=$(shell go list ./... | grep -v '/vendor/' | grep -v '_attic') +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 +all: check_tools get_vendor_deps build test ######################################## ### Build @@ -38,4 +38,4 @@ benchmark: # 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 check_tools get_tools get_vendor_deps test benchmark diff --git a/x/_attic/eyes/_gen.go b/x/_attic/eyes/_gen.go deleted file mode 100644 index a98feaf4e..000000000 --- a/x/_attic/eyes/_gen.go +++ /dev/null @@ -1,6 +0,0 @@ -package main - -import ( - _ "github.com/tendermint/go-wire/gen" - _ "github.com/clipperhouse/stringer" -) diff --git a/x/_attic/eyes/commands/query.go b/x/_attic/eyes/commands/query.go deleted file mode 100644 index 171a7c72d..000000000 --- a/x/_attic/eyes/commands/query.go +++ /dev/null @@ -1,44 +0,0 @@ -package commands - -import ( - "encoding/hex" - - "github.com/spf13/cobra" - "github.com/spf13/viper" - - cmn "github.com/tendermint/tmlibs/common" - - "github.com/cosmos/cosmos-sdk/client/commands" - "github.com/cosmos/cosmos-sdk/client/commands/query" - "github.com/cosmos/cosmos-sdk/modules/eyes" - "github.com/cosmos/cosmos-sdk/util" -) - -// EyesQueryCmd - command to query raw data -var EyesQueryCmd = &cobra.Command{ - Use: "eyes [key]", - Short: "Get data stored under key in eyes", - RunE: commands.RequireInit(eyesQueryCmd), -} - -func eyesQueryCmd(cmd *cobra.Command, args []string) error { - var res eyes.Data - - arg, err := commands.GetOneArg(args, "key") - if err != nil { - return err - } - key, err := hex.DecodeString(cmn.StripHex(arg)) - if err != nil { - return err - } - - key = util.PrefixedKey(eyes.Name, key) - prove := !viper.GetBool(commands.FlagTrustNode) - height, err := query.GetParsed(key, &res, query.GetHeight(), prove) - if err != nil { - return err - } - - return query.OutputProof(res, height) -} diff --git a/x/_attic/eyes/commands/tx.go b/x/_attic/eyes/commands/tx.go deleted file mode 100644 index 7db82f3fd..000000000 --- a/x/_attic/eyes/commands/tx.go +++ /dev/null @@ -1,63 +0,0 @@ -package commands - -import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client/commands" - "github.com/cosmos/cosmos-sdk/client/commands/txs" - "github.com/cosmos/cosmos-sdk/modules/eyes" -) - -// SetTxCmd is CLI command to set data -var SetTxCmd = &cobra.Command{ - Use: "set", - Short: "Sets a key value pair", - RunE: commands.RequireInit(setTxCmd), -} - -// RemoveTxCmd is CLI command to remove data -var RemoveTxCmd = &cobra.Command{ - Use: "remove", - Short: "Removes a key value pair", - RunE: commands.RequireInit(removeTxCmd), -} - -const ( - // FlagKey is the cli flag to set the key - FlagKey = "key" - // FlagValue is the cli flag to set the value - FlagValue = "value" -) - -func init() { - SetTxCmd.Flags().String(FlagKey, "", "Key to store data under (hex)") - SetTxCmd.Flags().String(FlagValue, "", "Data to store (hex)") - - RemoveTxCmd.Flags().String(FlagKey, "", "Key under which to remove data (hex)") -} - -// setTxCmd creates a SetTx, wraps, signs, and delivers it -func setTxCmd(cmd *cobra.Command, args []string) error { - key, err := commands.ParseHexFlag(FlagKey) - if err != nil { - return err - } - value, err := commands.ParseHexFlag(FlagValue) - if err != nil { - return err - } - - tx := eyes.NewSetTx(key, value) - return txs.DoTx(tx) -} - -// removeTxCmd creates a RemoveTx, wraps, signs, and delivers it -func removeTxCmd(cmd *cobra.Command, args []string) error { - key, err := commands.ParseHexFlag(FlagKey) - if err != nil { - return err - } - - tx := eyes.NewRemoveTx(key) - return txs.DoTx(tx) -} diff --git a/x/_attic/eyes/errors.go b/x/_attic/eyes/errors.go deleted file mode 100644 index ae7babc6c..000000000 --- a/x/_attic/eyes/errors.go +++ /dev/null @@ -1,23 +0,0 @@ -package eyes - -import ( - "fmt" - - abci "github.com/tendermint/abci/types" - - "github.com/cosmos/cosmos-sdk/errors" -) - -var ( - errMissingData = fmt.Errorf("All tx fields must be filled") - - malformed = abci.CodeType_EncodingError -) - -//nolint -func ErrMissingData() errors.TMError { - return errors.WithCode(errMissingData, malformed) -} -func IsMissingDataErr(err error) bool { - return errors.IsSameError(errMissingData, err) -} diff --git a/x/_attic/eyes/eyestxinner_wrapper.go b/x/_attic/eyes/eyestxinner_wrapper.go deleted file mode 100644 index f93704ab8..000000000 --- a/x/_attic/eyes/eyestxinner_wrapper.go +++ /dev/null @@ -1,62 +0,0 @@ -// Generated by: main -// TypeWriter: wrapper -// Directive: +gen on EyesTxInner - -package eyes - -import ( - "github.com/tendermint/go-wire/data" -) - -// Auto-generated adapters for happily unmarshaling interfaces -// Apache License 2.0 -// Copyright (c) 2017 Ethan Frey (ethan.frey@tendermint.com) - -type EyesTx struct { - EyesTxInner "json:\"unwrap\"" -} - -var EyesTxMapper = data.NewMapper(EyesTx{}) - -func (h EyesTx) MarshalJSON() ([]byte, error) { - return EyesTxMapper.ToJSON(h.EyesTxInner) -} - -func (h *EyesTx) UnmarshalJSON(data []byte) (err error) { - parsed, err := EyesTxMapper.FromJSON(data) - if err == nil && parsed != nil { - h.EyesTxInner = parsed.(EyesTxInner) - } - return err -} - -// Unwrap recovers the concrete interface safely (regardless of levels of embeds) -func (h EyesTx) Unwrap() EyesTxInner { - hi := h.EyesTxInner - for wrap, ok := hi.(EyesTx); ok; wrap, ok = hi.(EyesTx) { - hi = wrap.EyesTxInner - } - return hi -} - -func (h EyesTx) Empty() bool { - return h.EyesTxInner == nil -} - -/*** below are bindings for each implementation ***/ - -func init() { - EyesTxMapper.RegisterImplementation(SetTx{}, "set", 0x1) -} - -func (hi SetTx) Wrap() EyesTx { - return EyesTx{hi} -} - -func init() { - EyesTxMapper.RegisterImplementation(RemoveTx{}, "remove", 0x2) -} - -func (hi RemoveTx) Wrap() EyesTx { - return EyesTx{hi} -} diff --git a/x/_attic/eyes/handler.go b/x/_attic/eyes/handler.go deleted file mode 100644 index 4b8ab3f91..000000000 --- a/x/_attic/eyes/handler.go +++ /dev/null @@ -1,104 +0,0 @@ -package eyes - -import ( - wire "github.com/tendermint/go-wire" - "github.com/tendermint/tmlibs/log" - - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/errors" -) - -const ( - // Name is used to register this module - Name = "eyes" - // CostSet is the gas needed for the set operation - CostSet uint64 = 10 - // CostRemove is the gas needed for the remove operation - CostRemove = 10 -) - -// Handler allows us to set and remove data -type Handler struct{} - -var _ sdk.Handler = Handler{} - -// NewHandler makes a role handler to modify data -func NewHandler() Handler { - return Handler{} -} - -// InitState - sets the genesis state - implements InitStater -func (h Handler) InitState(l log.Logger, store sdk.SimpleDB, - module, key, value string) (log string, err error) { - - if module != Name { - return "", errors.ErrUnknownModule(module) - } - store.Set([]byte(key), []byte(value)) - return key, nil -} - -// CheckTx verifies if the transaction is properly formated -func (h Handler) CheckTx(ctx sdk.Context, store sdk.SimpleDB, - msg interface{}) (res sdk.CheckResult, err error) { - - tx := sdk.MustGetTx(msg).(EyesTx) - if err := tx.ValidateBasic(); err != nil { - return res, err - } - - switch tx.Unwrap().(type) { - case SetTx: - res = sdk.NewCheck(CostSet, "") - case RemoveTx: - res = sdk.NewCheck(CostRemove, "") - default: - err = errors.ErrUnknownTxType(tx) - } - return -} - -// DeliverTx tries to create a new role. -// -// Returns an error if the role already exists -func (h Handler) DeliverTx(ctx sdk.Context, store sdk.SimpleDB, - msg interface{}) (res sdk.DeliverResult, err error) { - - tx := sdk.MustGetTx(msg).(EyesTx) - if err := tx.ValidateBasic(); err != nil { - return res, err - } - - switch t := tx.Unwrap().(type) { - case SetTx: - res, err = h.doSetTx(ctx, store, t) - case RemoveTx: - res, err = h.doRemoveTx(ctx, store, t) - default: - err = errors.ErrUnknownTxType(tx) - } - return -} - -// doSetTx writes to the store, overwriting any previous value -// note that an empty response in DeliverTx is OK with no log or data returned -func (h Handler) doSetTx(ctx sdk.Context, store sdk.SimpleDB, - tx SetTx) (res sdk.DeliverResult, err error) { - - data := NewData(tx.Value, ctx.BlockHeight()) - store.Set(tx.Key, wire.BinaryBytes(data)) - return -} - -// doRemoveTx deletes the value from the store and returns the last value -// here we let res.Data to return the value over abci -func (h Handler) doRemoveTx(ctx sdk.Context, store sdk.SimpleDB, - tx RemoveTx) (res sdk.DeliverResult, err error) { - - // we set res.Data so it gets returned to the client over the abci interface - res.Data = store.Get(tx.Key) - if len(res.Data) != 0 { - store.Remove(tx.Key) - } - return -} diff --git a/x/_attic/eyes/handler_test.go b/x/_attic/eyes/handler_test.go deleted file mode 100644 index 0cc688a2b..000000000 --- a/x/_attic/eyes/handler_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package eyes - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - wire "github.com/tendermint/go-wire" - - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/state" - "github.com/cosmos/cosmos-sdk/util" -) - -func TestHandler(t *testing.T) { - assert, require := assert.New(t), require.New(t) - - key := []byte("one") - val := []byte("foo") - var height uint64 = 123 - - h := NewHandler() - ctx := util.MockContext("role-chain", height) - store := state.NewMemKVStore() - - set := sdk.WrapTx(NewSetTx(key, val)) - remove := sdk.WrapTx(NewRemoveTx(key)) - invalid := sdk.WrapTx(NewSetTx(nil, nil)) - - // make sure pricing makes sense - cres, err := h.CheckTx(ctx, store, set) - require.Nil(err, "%+v", err) - require.True(cres.GasAllocated > 5, "%#v", cres) - - // set the value, no error - dres, err := h.DeliverTx(ctx, store, set) - require.Nil(err, "%+v", err) - - // get the data - var data Data - bs := store.Get(key) - require.NotEmpty(bs) - err = wire.ReadBinaryBytes(bs, &data) - require.Nil(err, "%+v", err) - assert.Equal(height, data.SetAt) - assert.EqualValues(val, data.Value) - - // make sure pricing makes sense - cres, err = h.CheckTx(ctx, store, remove) - require.Nil(err, "%+v", err) - require.True(cres.GasAllocated > 5, "%#v", cres) - - // remove the data returns the same as the above query - dres, err = h.DeliverTx(ctx, store, remove) - require.Nil(err, "%+v", err) - require.EqualValues(bs, dres.Data) - - // make sure invalid fails both ways - _, err = h.CheckTx(ctx, store, invalid) - require.NotNil(err) - _, err = h.DeliverTx(ctx, store, invalid) - require.NotNil(err) -} diff --git a/x/_attic/eyes/store.go b/x/_attic/eyes/store.go deleted file mode 100644 index 38d892064..000000000 --- a/x/_attic/eyes/store.go +++ /dev/null @@ -1,20 +0,0 @@ -package eyes - -import "github.com/tendermint/go-wire/data" - -// Data is the struct we use to store in the merkle tree -type Data struct { - // SetAt is the block height this was set at - SetAt uint64 `json:"set_at"` - // Value is the data that was stored. - // data.Bytes is like []byte but json encodes as hex not base64 - Value data.Bytes `json:"value"` -} - -// NewData creates a new Data item -func NewData(value []byte, setAt uint64) Data { - return Data{ - SetAt: setAt, - Value: value, - } -} diff --git a/x/_attic/eyes/tx.go b/x/_attic/eyes/tx.go deleted file mode 100644 index db83ad295..000000000 --- a/x/_attic/eyes/tx.go +++ /dev/null @@ -1,53 +0,0 @@ -package eyes - -import ( - "github.com/tendermint/go-wire/data" -) - -// DO NOT USE THIS INTERFACE. -// You probably want to use EyesTx -// +gen wrapper:"EyesTx,Impl[SetTx,RemoveTx],set,remove" -type EyesTxInner interface { - ValidateBasic() error -} - -// func init() { -// sdk.TxMapper. -// RegisterImplementation(SetTx{}, TypeSet, ByteSet). -// RegisterImplementation(RemoveTx{}, TypeRemove, ByteRemove) -// } - -// SetTx sets a key-value pair -type SetTx struct { - Key data.Bytes `json:"key"` - Value data.Bytes `json:"value"` -} - -func NewSetTx(key, value []byte) EyesTx { - return SetTx{Key: key, Value: value}.Wrap() -} - -// ValidateBasic makes sure it is valid -func (t SetTx) ValidateBasic() error { - if len(t.Key) == 0 || len(t.Value) == 0 { - return ErrMissingData() - } - return nil -} - -// RemoveTx deletes the value at this key, returns old value -type RemoveTx struct { - Key data.Bytes `json:"key"` -} - -func NewRemoveTx(key []byte) EyesTx { - return RemoveTx{Key: key}.Wrap() -} - -// ValidateBasic makes sure it is valid -func (t RemoveTx) ValidateBasic() error { - if len(t.Key) == 0 { - return ErrMissingData() - } - return nil -} diff --git a/x/_attic/fee/commands/wrap.go b/x/_attic/fee/commands/wrap.go deleted file mode 100644 index 50ac91eb2..000000000 --- a/x/_attic/fee/commands/wrap.go +++ /dev/null @@ -1,59 +0,0 @@ -package commands - -import ( - "github.com/spf13/pflag" - "github.com/spf13/viper" - - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/client/commands" - txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs" - "github.com/cosmos/cosmos-sdk/modules/coin" - "github.com/cosmos/cosmos-sdk/modules/fee" -) - -//nolint -const ( - FlagFee = "fee" - FlagPayer = "payer" -) - -// FeeWrapper wraps a tx with an optional fee payment -type FeeWrapper struct{} - -var _ txcmd.Wrapper = FeeWrapper{} - -// Wrap checks for FlagFee and if present wraps the tx with a -// FeeTx of the given amount, paid by the signer -func (FeeWrapper) Wrap(tx sdk.Tx) (res sdk.Tx, err error) { - //parse the fee and amounts into coin types - toll, err := coin.ParseCoin(viper.GetString(FlagFee)) - if err != nil { - return res, err - } - // if no fee, do nothing, otherwise wrap it - if toll.IsZero() { - return tx, nil - } - - payer, err := readPayer() - if err != nil { - return res, err - } - - res = fee.NewFee(tx, toll, payer) - return -} - -// Register adds the sequence flags to the cli -func (FeeWrapper) Register(fs *pflag.FlagSet) { - fs.String(FlagFee, "0mycoin", "Coins for the transaction fee of the format ") - fs.String(FlagPayer, "", "Account to pay fee if not current signer (for multisig)") -} - -func readPayer() (sdk.Actor, error) { - payer := viper.GetString(FlagPayer) - if payer == "" { - return txcmd.GetSignerAct(), nil - } - return commands.ParseActor(payer) -} diff --git a/x/_attic/fee/error_test.go b/x/_attic/fee/error_test.go deleted file mode 100644 index 4d255b880..000000000 --- a/x/_attic/fee/error_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package fee - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestErrors(t *testing.T) { - assert := assert.New(t) - - e := ErrInsufficientFees() - assert.True(IsInsufficientFeesErr(e)) - assert.False(IsWrongFeeDenomErr(e)) - - e2 := ErrWrongFeeDenom("atom") - assert.False(IsInsufficientFeesErr(e2)) - assert.True(IsWrongFeeDenomErr(e2)) -} diff --git a/x/_attic/fee/errors.go b/x/_attic/fee/errors.go deleted file mode 100644 index 80cc9818a..000000000 --- a/x/_attic/fee/errors.go +++ /dev/null @@ -1,39 +0,0 @@ -//nolint -package fee - -import ( - "fmt" - - abci "github.com/tendermint/abci/types" - - "github.com/cosmos/cosmos-sdk/errors" -) - -var ( - errInsufficientFees = fmt.Errorf("Insufficient fees") - errWrongFeeDenom = fmt.Errorf("Required fee denomination") - errSkipFees = fmt.Errorf("Skip fees") - - invalidInput = abci.CodeType_BaseInvalidInput -) - -func ErrInsufficientFees() errors.TMError { - return errors.WithCode(errInsufficientFees, invalidInput) -} -func IsInsufficientFeesErr(err error) bool { - return errors.IsSameError(errInsufficientFees, err) -} - -func ErrWrongFeeDenom(denom string) errors.TMError { - return errors.WithMessage(denom, errWrongFeeDenom, invalidInput) -} -func IsWrongFeeDenomErr(err error) bool { - return errors.IsSameError(errWrongFeeDenom, err) -} - -func ErrSkipFees() errors.TMError { - return errors.WithCode(errSkipFees, invalidInput) -} -func IsSkipFeesErr(err error) bool { - return errors.IsSameError(errSkipFees, err) -} diff --git a/x/_attic/fee/handler.go b/x/_attic/fee/handler.go deleted file mode 100644 index 0a1df3f49..000000000 --- a/x/_attic/fee/handler.go +++ /dev/null @@ -1,117 +0,0 @@ -package fee - -import ( - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/errors" - "github.com/cosmos/cosmos-sdk/modules/coin" - "github.com/cosmos/cosmos-sdk/stack" - "github.com/cosmos/cosmos-sdk/state" -) - -// NameFee - namespace for the fee module -const NameFee = "fee" - -// Bank is a default location for the fees, but pass anything into -// the middleware constructor -var Bank = sdk.Actor{App: NameFee, Address: []byte("bank")} - -// SimpleFeeMiddleware - middleware for fee checking, constant amount -// It used modules.coin to move the money -type SimpleFeeMiddleware struct { - // the fee must be the same denomination and >= this amount - // if the amount is 0, then the fee tx wrapper is optional - MinFee coin.Coin - // all fees go here, which could be a dump (Bank) or something reachable - // by other app logic - Collector sdk.Actor - stack.PassInitState - stack.PassInitValidate -} - -var _ stack.Middleware = SimpleFeeMiddleware{} - -// NewSimpleFeeMiddleware returns a fee handler with a fixed minimum fee. -// -// If minFee is 0, then the FeeTx is optional -func NewSimpleFeeMiddleware(minFee coin.Coin, collector sdk.Actor) SimpleFeeMiddleware { - return SimpleFeeMiddleware{ - MinFee: minFee, - Collector: collector, - } -} - -// Name - return the namespace for the fee module -func (SimpleFeeMiddleware) Name() string { - return NameFee -} - -// CheckTx - check the transaction -func (h SimpleFeeMiddleware) CheckTx(ctx sdk.Context, store state.SimpleDB, tx sdk.Tx, next sdk.Checker) (res sdk.CheckResult, err error) { - fee, err := h.verifyFee(ctx, tx) - if err != nil { - if IsSkipFeesErr(err) { - return next.CheckTx(ctx, store, tx) - } - return res, err - } - - var paid, used uint64 - if !fee.Fee.IsZero() { // now, try to make a IPC call to coins... - send := coin.NewSendOneTx(fee.Payer, h.Collector, coin.Coins{fee.Fee}) - sendRes, err := next.CheckTx(ctx, store, send) - if err != nil { - return res, err - } - paid = uint64(fee.Fee.Amount) - used = sendRes.GasAllocated - } - - res, err = next.CheckTx(ctx, store, fee.Tx) - // add the given fee to the price for gas, plus one query - if err == nil { - res.GasPayment += paid - res.GasAllocated += used - } - return res, err -} - -// DeliverTx - send the fee handler transaction -func (h SimpleFeeMiddleware) DeliverTx(ctx sdk.Context, store state.SimpleDB, tx sdk.Tx, next sdk.Deliver) (res sdk.DeliverResult, err error) { - fee, err := h.verifyFee(ctx, tx) - if IsSkipFeesErr(err) { - return next.DeliverTx(ctx, store, tx) - } - if err != nil { - return res, err - } - - if !fee.Fee.IsZero() { // now, try to make a IPC call to coins... - send := coin.NewSendOneTx(fee.Payer, h.Collector, coin.Coins{fee.Fee}) - _, err = next.DeliverTx(ctx, store, send) - if err != nil { - return res, err - } - } - return next.DeliverTx(ctx, store, fee.Tx) -} - -func (h SimpleFeeMiddleware) verifyFee(ctx sdk.Context, tx sdk.Tx) (Fee, error) { - feeTx, ok := tx.Unwrap().(Fee) - if !ok { - // the fee wrapper is not required if there is no minimum - if h.MinFee.IsZero() { - return feeTx, ErrSkipFees() - } - return feeTx, errors.ErrInvalidFormat(TypeFees, tx) - } - - // see if it is the proper denom and big enough - fee := feeTx.Fee - if fee.Denom != h.MinFee.Denom { - return feeTx, ErrWrongFeeDenom(h.MinFee.Denom) - } - if !fee.IsGTE(h.MinFee) { - return feeTx, ErrInsufficientFees() - } - return feeTx, nil -} diff --git a/x/_attic/fee/handler_test.go b/x/_attic/fee/handler_test.go deleted file mode 100644 index a4fc0cc9b..000000000 --- a/x/_attic/fee/handler_test.go +++ /dev/null @@ -1,141 +0,0 @@ -package fee_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/tendermint/tmlibs/log" - - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/modules/coin" - "github.com/cosmos/cosmos-sdk/modules/fee" - "github.com/cosmos/cosmos-sdk/stack" - "github.com/cosmos/cosmos-sdk/state" -) - -func TestFeeChecks(t *testing.T) { - assert := assert.New(t) - require := require.New(t) - - atom := func(i int64) coin.Coin { return coin.Coin{"atom", i} } - eth := func(i int64) coin.Coin { return coin.Coin{"eth", i} } - atoms := func(i int64) coin.Coins { return coin.Coins{{"atom", i}} } - wallet := func(i, j int64) coin.Coins { return coin.Coins{atom(i), eth(j)} } - - // some coin amounts... - zero := coin.Coin{} - mixed := wallet(1200, 55) - pure := atoms(46657) - - // these are some accounts - collector := sdk.Actor{App: fee.NameFee, Address: []byte("mine")} - key1 := coin.NewAccountWithKey(mixed) - key2 := coin.NewAccountWithKey(pure) - act1, act2 := key1.Actor(), key2.Actor() - - // set up the apps.... - disp := stack.NewDispatcher( - // OKHandler will just return success to a RawTx - stack.WrapHandler(stack.OKHandler{}), - // coin is needed to handle the IPC call from Fee middleware - coin.NewHandler(), - ) - // app1 requires no fees - app1 := stack.New(fee.NewSimpleFeeMiddleware(atom(0), collector)).Use(disp) - // app2 requires 2 atom - app2 := stack.New(fee.NewSimpleFeeMiddleware(atom(2), collector)).Use(disp) - - // set up the store and init the accounts - store := state.NewMemKVStore() - l := log.NewNopLogger() - _, err := app1.InitState(l, store, "coin", "account", key1.MakeOption()) - require.Nil(err, "%+v", err) - _, err = app2.InitState(l, store, "coin", "account", key2.MakeOption()) - require.Nil(err, "%+v", err) - - // feeCost is what we expect if the fee is properly paid - feeCost := coin.CostSend * 2 - cases := []struct { - valid bool - // this is the middleware stack to test - app sdk.Handler - // they sign the tx - signer sdk.Actor - // wrap with the given fee if hasFee is true - hasFee bool - payer sdk.Actor - fee coin.Coin - // expected balance after the tx - left coin.Coins - collected coin.Coins - // expected gas allocated - expectedCost uint64 - }{ - // make sure it works with no fee (control group) - {true, app1, act1, false, act1, zero, mixed, nil, 0}, - {true, app1, act2, false, act2, zero, pure, nil, 0}, - - // no fee or too low is rejected - {false, app2, act1, false, act1, zero, mixed, nil, 0}, - {false, app2, act2, false, act2, zero, pure, nil, 0}, - {false, app2, act1, true, act1, zero, mixed, nil, 0}, - {false, app2, act2, true, act2, atom(1), pure, nil, 0}, - - // proper fees are transfered in both cases - {true, app1, act1, true, act1, atom(1), wallet(1199, 55), atoms(1), feeCost}, - {true, app2, act2, true, act2, atom(57), atoms(46600), atoms(58), feeCost}, - - // // fee must be the proper type... - {false, app1, act1, true, act1, eth(5), wallet(1199, 55), atoms(58), 0}, - - // signature must match - {false, app2, act1, true, act2, atom(5), atoms(46600), atoms(58), 0}, - - // send only works within limits - {true, app2, act1, true, act1, atom(1100), wallet(99, 55), atoms(1158), feeCost}, - {false, app2, act1, true, act1, atom(500), wallet(99, 55), atoms(1158), 0}, - } - - for i, tc := range cases { - // build the tx - tx := stack.NewRawTx([]byte{7, 8, 9}) - if tc.hasFee { - tx = fee.NewFee(tx, tc.fee, tc.payer) - } - - // set up the permissions - ctx := stack.MockContext("x", 1).WithPermissions(tc.signer) - - // call checktx... - cres, err := tc.app.CheckTx(ctx, store, tx) - if tc.valid { - assert.Nil(err, "%d: %+v", i, err) - assert.EqualValues(tc.fee.Amount, cres.GasPayment) - assert.EqualValues(tc.expectedCost, cres.GasAllocated) - } else { - assert.NotNil(err, "%d", i) - } - - // call delivertx... - _, err = tc.app.DeliverTx(ctx, store, tx) - if tc.valid { - assert.Nil(err, "%d: %+v", i, err) - } else { - assert.NotNil(err, "%d", i) - } - - // check the account balance afterwards.... - cspace := stack.PrefixedStore(coin.NameCoin, store) - acct, err := coin.GetAccount(cspace, tc.payer) - require.Nil(err, "%d: %+v", i, err) - assert.Equal(tc.left, acct.Coins, "%d", i) - - // check the collected balance afterwards.... - acct, err = coin.GetAccount(cspace, collector) - require.Nil(err, "%d: %+v", i, err) - assert.Equal(tc.collected, acct.Coins, "%d", i) - } - -} diff --git a/x/_attic/fee/tx.go b/x/_attic/fee/tx.go deleted file mode 100644 index 43250a7c8..000000000 --- a/x/_attic/fee/tx.go +++ /dev/null @@ -1,44 +0,0 @@ -package fee - -import ( - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/modules/coin" -) - -// nolint -const ( - ByteFees = 0x28 - TypeFees = NameFee + "/tx" -) - -func init() { - sdk.TxMapper. - RegisterImplementation(Fee{}, TypeFees, ByteFees) -} - -/**** Fee ****/ - -// Fee attaches a fee payment to the embedded tx -type Fee struct { - // Gas coin.Coin `json:"gas"` // ????? - Fee coin.Coin `json:"fee"` - Payer sdk.Actor `json:"payer"` // the address who pays the fee - Tx sdk.Tx `json:"tx"` -} - -// NewFee wraps a tx with a promised fee from this actor -func NewFee(tx sdk.Tx, fee coin.Coin, payer sdk.Actor) sdk.Tx { - return Fee{Tx: tx, Fee: fee, Payer: payer}.Wrap() -} - -// nolint - TxInner Functions -func (f Fee) ValidateBasic() error { - // TODO: more checks - return f.Tx.ValidateBasic() -} -func (f Fee) Wrap() sdk.Tx { - return sdk.Tx{f} -} -func (f Fee) Next() sdk.Tx { - return f.Tx -} diff --git a/x/_attic/logger/logger.go b/x/_attic/logger/logger.go deleted file mode 100644 index 51ef49f2b..000000000 --- a/x/_attic/logger/logger.go +++ /dev/null @@ -1,71 +0,0 @@ -package util - -import ( - "time" - - abci "github.com/tendermint/abci/types" - - sdk "github.com/cosmos/cosmos-sdk" -) - -// Logger writes out log messages on every request -type Logger struct{} - -var _ sdk.Decorator = Logger{} - -// CheckTx logs time and result - fulfills Middlware interface -func (Logger) CheckTx(ctx sdk.Context, store sdk.SimpleDB, tx interface{}, next sdk.Checker) (res sdk.CheckResult, err error) { - start := time.Now() - res, err = next.CheckTx(ctx, store, tx) - delta := time.Now().Sub(start) - // TODO: log some info on the tx itself? - l := ctx.With("duration", micros(delta)) - if err == nil { - l.Debug("CheckTx", "log", res.Log) - } else { - l.Info("CheckTx", "err", err) - } - return -} - -// DeliverTx logs time and result - fulfills Middlware interface -func (Logger) DeliverTx(ctx sdk.Context, store sdk.SimpleDB, tx interface{}, next sdk.Deliverer) (res sdk.DeliverResult, err error) { - start := time.Now() - res, err = next.DeliverTx(ctx, store, tx) - delta := time.Now().Sub(start) - // TODO: log some info on the tx itself? - l := ctx.With("duration", micros(delta)) - if err == nil { - l.Info("DeliverTx", "log", res.Log) - } else { - l.Error("DeliverTx", "err", err) - } - return -} - -// LogTicker wraps any ticker and records the time it takes. -// Pass in a name to be logged with this to separate out various -// tickers -func LogTicker(clock sdk.Ticker, name string) sdk.Ticker { - res := func(ctx sdk.Context, s sdk.SimpleDB) ([]*abci.Validator, error) { - start := time.Now() - vals, err := clock.Tick(ctx, s) - delta := time.Now().Sub(start) - l := ctx.With("duration", micros(delta)) - if name != "" { - l = l.With("name", name) - } - if err == nil { - l.Info("Tock") - } else { - l.Error("Tock", "err", err) - } - return vals, err - } - return sdk.TickerFunc(res) -} - -// micros returns how many microseconds passed in a call -func micros(d time.Duration) int { - return int(d.Seconds() * 1000000) -} diff --git a/x/_attic/nonce/commands/query.go b/x/_attic/nonce/commands/query.go deleted file mode 100644 index 7021c8ca5..000000000 --- a/x/_attic/nonce/commands/query.go +++ /dev/null @@ -1,53 +0,0 @@ -package commands - -import ( - "strings" - - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/viper" - - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/commands" - "github.com/cosmos/cosmos-sdk/client/commands/query" - "github.com/cosmos/cosmos-sdk/modules/nonce" - "github.com/cosmos/cosmos-sdk/stack" -) - -// NonceQueryCmd - command to query an nonce account -var NonceQueryCmd = &cobra.Command{ - Use: "nonce [address]", - Short: "Get details of a nonce sequence number, with proof", - RunE: commands.RequireInit(nonceQueryCmd), -} - -func nonceQueryCmd(cmd *cobra.Command, args []string) error { - if len(args) == 0 { - return errors.New("Missing required argument [address]") - } - addr := strings.Join(args, ",") - - signers, err := commands.ParseActors(addr) - if err != nil { - return err - } - - seq, height, err := doNonceQuery(signers) - if err != nil { - return err - } - - return query.OutputProof(seq, height) -} - -func doNonceQuery(signers []sdk.Actor) (sequence uint32, height uint64, err error) { - key := stack.PrefixedKey(nonce.NameNonce, nonce.GetSeqKey(signers)) - prove := !viper.GetBool(commands.FlagTrustNode) - height, err = query.GetParsed(key, &sequence, query.GetHeight(), prove) - if client.IsNoDataErr(err) { - // no data, return sequence 0 - return 0, 0, nil - } - return -} diff --git a/x/_attic/nonce/commands/wrap.go b/x/_attic/nonce/commands/wrap.go deleted file mode 100644 index c7e5be704..000000000 --- a/x/_attic/nonce/commands/wrap.go +++ /dev/null @@ -1,83 +0,0 @@ -package commands - -import ( - "fmt" - - "github.com/spf13/pflag" - "github.com/spf13/viper" - - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/client/commands" - txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs" - "github.com/cosmos/cosmos-sdk/modules/nonce" -) - -// nolint -const ( - FlagSequence = "sequence" - FlagNonceKey = "nonce-key" -) - -// NonceWrapper wraps a tx with a nonce -type NonceWrapper struct{} - -var _ txcmd.Wrapper = NonceWrapper{} - -// Wrap grabs the sequence number from the flag and wraps -// the tx with this nonce. Grabs the permission from the signer, -// as we still only support single sig on the cli -func (NonceWrapper) Wrap(tx sdk.Tx) (res sdk.Tx, err error) { - - signers, err := readNonceKey() - if err != nil { - return res, err - } - - seq, err := readSequence(signers) - if err != nil { - return res, err - } - - res = nonce.NewTx(seq, signers, tx) - return -} - -// Register adds the sequence flags to the cli -func (NonceWrapper) Register(fs *pflag.FlagSet) { - fs.Int(FlagSequence, -1, "Sequence number for this transaction") - fs.String(FlagNonceKey, "", "Set of comma-separated addresses for the nonce (for multisig)") -} - -func readNonceKey() ([]sdk.Actor, error) { - nonce := viper.GetString(FlagNonceKey) - if nonce == "" { - return []sdk.Actor{txcmd.GetSignerAct()}, nil - } - return commands.ParseActors(nonce) -} - -// read the sequence from the flag or query for it if flag is -1 -func readSequence(signers []sdk.Actor) (seq uint32, err error) { - //add the nonce tx layer to the tx - seqFlag := viper.GetInt(FlagSequence) - - switch { - case seqFlag > 0: - seq = uint32(seqFlag) - - case seqFlag == -1: - //autocalculation for default sequence - seq, _, err = doNonceQuery(signers) - if err != nil { - return - } - - //increase the sequence by 1! - seq++ - - default: - err = fmt.Errorf("sequence must be either greater than 0, or -1 for autocalculation") - } - - return -} diff --git a/x/_attic/nonce/errors.go b/x/_attic/nonce/errors.go deleted file mode 100644 index 0d77b7984..000000000 --- a/x/_attic/nonce/errors.go +++ /dev/null @@ -1,41 +0,0 @@ -//nolint -package nonce - -import ( - "fmt" - - abci "github.com/tendermint/abci/types" - - "github.com/cosmos/cosmos-sdk/errors" -) - -var ( - errNoNonce = fmt.Errorf("Tx doesn't contain nonce") - errNotMember = fmt.Errorf("Nonce contains non-permissioned member") - errZeroSequence = fmt.Errorf("Sequence number cannot be zero") - errNoSigners = fmt.Errorf("There are no signers") - errTxEmpty = fmt.Errorf("The provided Tx is empty") - - unauthorized = abci.CodeType_Unauthorized - badNonce = abci.CodeType_BadNonce - invalidInput = abci.CodeType_BaseInvalidInput -) - -func ErrBadNonce(got, expected uint32) errors.TMError { - return errors.WithCode(fmt.Errorf("Bad nonce sequence, got %d, expected %d", got, expected), badNonce) -} -func ErrNoNonce() errors.TMError { - return errors.WithCode(errNoNonce, badNonce) -} -func ErrNotMember() errors.TMError { - return errors.WithCode(errNotMember, unauthorized) -} -func ErrZeroSequence() errors.TMError { - return errors.WithCode(errZeroSequence, invalidInput) -} -func ErrNoSigners() errors.TMError { - return errors.WithCode(errNoSigners, invalidInput) -} -func ErrTxEmpty() errors.TMError { - return errors.WithCode(errTxEmpty, invalidInput) -} diff --git a/x/_attic/nonce/replaycheck.go b/x/_attic/nonce/replaycheck.go deleted file mode 100644 index 521e5ec58..000000000 --- a/x/_attic/nonce/replaycheck.go +++ /dev/null @@ -1,77 +0,0 @@ -package nonce - -import ( - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/stack" - "github.com/cosmos/cosmos-sdk/state" -) - -//nolint -const ( - NameNonce = "nonce" - CostNonce = 10 -) - -// ReplayCheck uses the sequence to check for replay attacks -type ReplayCheck struct { - stack.PassInitState - stack.PassInitValidate -} - -// Name of the module - fulfills Middleware interface -func (ReplayCheck) Name() string { - return NameNonce -} - -var _ stack.Middleware = ReplayCheck{} - -// CheckTx verifies tx is not being replayed - fulfills Middlware interface -func (r ReplayCheck) CheckTx(ctx sdk.Context, store state.SimpleDB, - tx sdk.Tx, next sdk.Checker) (res sdk.CheckResult, err error) { - - stx, err := r.checkIncrementNonceTx(ctx, store, tx) - if err != nil { - return res, err - } - - res, err = next.CheckTx(ctx, store, stx) - res.GasAllocated += CostNonce - return res, err -} - -// DeliverTx verifies tx is not being replayed - fulfills Middlware interface -// NOTE It is okay to modify the sequence before running the wrapped TX because if the -// wrapped Tx fails, the state changes are not applied -func (r ReplayCheck) DeliverTx(ctx sdk.Context, store state.SimpleDB, - tx sdk.Tx, next sdk.Deliver) (res sdk.DeliverResult, err error) { - - stx, err := r.checkIncrementNonceTx(ctx, store, tx) - if err != nil { - return res, err - } - - return next.DeliverTx(ctx, store, stx) -} - -// checkNonceTx varifies the nonce sequence, an increment sequence number -func (r ReplayCheck) checkIncrementNonceTx(ctx sdk.Context, store state.SimpleDB, - tx sdk.Tx) (sdk.Tx, error) { - - // make sure it is a the nonce Tx (Tx from this package) - nonceTx, ok := tx.Unwrap().(Tx) - if !ok { - return tx, ErrNoNonce() - } - - err := nonceTx.ValidateBasic() - if err != nil { - return tx, err - } - - // check the nonce sequence number - err = nonceTx.CheckIncrementSeq(ctx, store) - if err != nil { - return tx, err - } - return nonceTx.Tx, nil -} diff --git a/x/_attic/nonce/rest/handlers.go b/x/_attic/nonce/rest/handlers.go deleted file mode 100644 index 05c0b2cd8..000000000 --- a/x/_attic/nonce/rest/handlers.go +++ /dev/null @@ -1,84 +0,0 @@ -package rest - -import ( - "fmt" - "net/http" - "strconv" - - "github.com/gorilla/mux" - "github.com/spf13/viper" - - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/commands" - "github.com/cosmos/cosmos-sdk/client/commands/query" - "github.com/cosmos/cosmos-sdk/errors" - "github.com/cosmos/cosmos-sdk/modules/coin" - "github.com/cosmos/cosmos-sdk/modules/nonce" - "github.com/cosmos/cosmos-sdk/stack" - wire "github.com/tendermint/go-wire" - "github.com/tendermint/tmlibs/common" -) - -// doQueryNonce is the HTTP handlerfunc to query a nonce -func doQueryNonce(w http.ResponseWriter, r *http.Request) { - args := mux.Vars(r) - signature := args["signature"] - actor, err := commands.ParseActor(signature) - if err != nil { - common.WriteError(w, err) - return - } - - var h int - qHeight := r.URL.Query().Get("height") - if qHeight != "" { - h, err = strconv.Atoi(qHeight) - if err != nil { - common.WriteError(w, err) - return - } - } - - actor = coin.ChainAddr(actor) - key := nonce.GetSeqKey([]sdk.Actor{actor}) - key = stack.PrefixedKey(nonce.NameNonce, key) - - prove := !viper.GetBool(commands.FlagTrustNode) - - // query sequence number - data, height, err := query.Get(key, h, prove) - if client.IsNoDataErr(err) { - err = fmt.Errorf("nonce empty for address: %q", signature) - common.WriteError(w, err) - return - } else if err != nil { - common.WriteError(w, err) - return - } - - // unmarshal sequence number - var seq uint32 - err = wire.ReadBinaryBytes(data, &seq) - if err != nil { - msg := fmt.Sprintf("Error reading sequence for %X", key) - common.WriteError(w, errors.ErrInternal(msg)) - return - } - - // write result to client - if err := query.FoutputProof(w, seq, height); err != nil { - common.WriteError(w, err) - } -} - -// mux.Router registrars - -// RegisterQueryNonce is a mux.Router handler that exposes GET -// method access on route /query/nonce/{signature} to query nonces -func RegisterQueryNonce(r *mux.Router) error { - r.HandleFunc("/query/nonce/{signature}", doQueryNonce).Methods("GET") - return nil -} - -// End of mux.Router registrars diff --git a/x/_attic/nonce/store.go b/x/_attic/nonce/store.go deleted file mode 100644 index 3ce2977d6..000000000 --- a/x/_attic/nonce/store.go +++ /dev/null @@ -1,30 +0,0 @@ -package nonce - -import ( - "fmt" - - wire "github.com/tendermint/go-wire" - - "github.com/cosmos/cosmos-sdk/errors" - "github.com/cosmos/cosmos-sdk/state" -) - -func getSeq(store state.SimpleDB, key []byte) (seq uint32, err error) { - data := store.Get(key) - if len(data) == 0 { - //if the key is not stored, its a new key with a sequence of zero! - return 0, nil - } - err = wire.ReadBinaryBytes(data, &seq) - if err != nil { - msg := fmt.Sprintf("Error reading sequence for %X", key) - return seq, errors.ErrInternal(msg) - } - return seq, nil -} - -func setSeq(store state.SimpleDB, key []byte, seq uint32) error { - bin := wire.BinaryBytes(seq) - store.Set(key, bin) - return nil // real stores can return error... -} diff --git a/x/_attic/nonce/tx.go b/x/_attic/nonce/tx.go deleted file mode 100644 index ba5b21c31..000000000 --- a/x/_attic/nonce/tx.go +++ /dev/null @@ -1,111 +0,0 @@ -/* -Package nonce - This module allows replay protection to be added to process stack. -This is achieved through the use of a sequence number for each unique set of signers. -Note that the sequence number for the single signing account "foo" will be unique -from the sequence number for a multi-sig account {"foo", "bar"} which would also be -unique from a different multi-sig account {"foo", "soup"} -*/ -package nonce - -import ( - "sort" - - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/state" -) - -// nolint -const ( - ByteNonce = 0x69 //TODO overhaul byte assign system don't make no sense! - TypeNonce = "nonce" -) - -func init() { - sdk.TxMapper.RegisterImplementation(Tx{}, TypeNonce, ByteNonce) -} - -// Tx - Nonce transaction structure, contains list of signers and current sequence number -type Tx struct { - Sequence uint32 `json:"sequence"` - Signers []sdk.Actor `json:"signers"` - Tx sdk.Tx `json:"tx"` -} - -var _ sdk.TxInner = &Tx{} - -// NewTx wraps the tx with a signable nonce -func NewTx(sequence uint32, signers []sdk.Actor, tx sdk.Tx) sdk.Tx { - return (Tx{ - Sequence: sequence, - Signers: signers, - Tx: tx, - }).Wrap() -} - -//nolint -func (n Tx) Wrap() sdk.Tx { - return sdk.Tx{n} -} -func (n Tx) ValidateBasic() error { - switch { - case n.Tx.Empty(): - return ErrTxEmpty() - case n.Sequence == 0: - return ErrZeroSequence() - case len(n.Signers) == 0: - return ErrNoSigners() - } - return n.Tx.ValidateBasic() -} - -// CheckIncrementSeq - Check that the sequence number is one more than the state sequence number -// and further increment the sequence number -// NOTE It is okay to modify the sequence before running the wrapped TX because if the -// wrapped Tx fails, the state changes are not applied -func (n Tx) CheckIncrementSeq(ctx sdk.Context, store state.SimpleDB) error { - - seqKey := n.getSeqKey() - - // check the current state - cur, err := getSeq(store, seqKey) - if err != nil { - return err - } - if n.Sequence != cur+1 { - return ErrBadNonce(n.Sequence, cur+1) - } - - // make sure they all signed - for _, s := range n.Signers { - if !ctx.HasPermission(s) { - return ErrNotMember() - } - } - - // increment the sequence by 1 - err = setSeq(store, seqKey, cur+1) - if err != nil { - return err - } - - return nil -} - -func (n Tx) getSeqKey() (seqKey []byte) { - return GetSeqKey(n.Signers) -} - -// GetSeqKey - Generate the sequence key as the concatenated list of signers, sorted by address. -func GetSeqKey(signers []sdk.Actor) (seqKey []byte) { - - // First copy the list of signers to sort as sort is done in place - signers2sort := make([]sdk.Actor, len(signers)) - copy(signers2sort, signers) - sort.Sort(sdk.ByAll(signers)) - - for _, signer := range signers { - seqKey = append(seqKey, signer.Bytes()...) - } - - return -} diff --git a/x/_attic/nonce/tx_test.go b/x/_attic/nonce/tx_test.go deleted file mode 100644 index e47a77116..000000000 --- a/x/_attic/nonce/tx_test.go +++ /dev/null @@ -1,119 +0,0 @@ -package nonce - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/stack" - "github.com/cosmos/cosmos-sdk/state" -) - -func TestNonce(t *testing.T) { - assert := assert.New(t) - require := require.New(t) - - // generic args here... - chainID := "my-chain" - chain2ID := "woohoo" - - height := uint64(100) - ctx := stack.MockContext(chainID, height) - store := state.NewMemKVStore() - - appName1 := "fooz" - appName2 := "foot" - - //root actors for the tests - act1 := sdk.Actor{ChainID: chainID, App: appName1, Address: []byte{1, 2, 3, 4}} - act2 := sdk.Actor{ChainID: chainID, App: appName1, Address: []byte{1, 1, 1, 1}} - act3 := sdk.Actor{ChainID: chainID, App: appName1, Address: []byte{3, 3, 3, 3}} - act1DiffChain := sdk.Actor{ChainID: chain2ID, App: appName1, Address: []byte{1, 2, 3, 4}} - act2DiffChain := sdk.Actor{ChainID: chain2ID, App: appName1, Address: []byte{1, 1, 1, 1}} - act3DiffChain := sdk.Actor{ChainID: chain2ID, App: appName1, Address: []byte{3, 3, 3, 3}} - act1DiffApp := sdk.Actor{ChainID: chainID, App: appName2, Address: []byte{1, 2, 3, 4}} - act2DiffApp := sdk.Actor{ChainID: chainID, App: appName2, Address: []byte{1, 1, 1, 1}} - act3DiffApp := sdk.Actor{ChainID: chainID, App: appName2, Address: []byte{3, 3, 3, 3}} - - // let's construct some tests to make the table a bit less verbose - set0 := []sdk.Actor{} - set1 := []sdk.Actor{act1} - set2 := []sdk.Actor{act2} - set12 := []sdk.Actor{act1, act2} - set21 := []sdk.Actor{act2, act1} - set123 := []sdk.Actor{act1, act2, act3} - set321 := []sdk.Actor{act3, act2, act1} - - //some more test cases for different chains and apps for each actor - set123Chain2 := []sdk.Actor{act1DiffChain, act2DiffChain, act3DiffChain} - set123App2 := []sdk.Actor{act1DiffApp, act2DiffApp, act3DiffApp} - set123MixedChains := []sdk.Actor{act1, act2DiffChain, act3} - set123MixedApps := []sdk.Actor{act1, act2DiffApp, act3} - - testList := []struct { - valid bool - seq uint32 - actors []sdk.Actor - signers []sdk.Actor - }{ - // one signer - {false, 0, set1, set1}, // seq 0 is no good - {false, 1, set1, set0}, // sig is required - {true, 1, set1, set1}, // sig and seq are good - {true, 2, set1, set1}, // increments each time - {false, 777, set1, set1}, // seq is too high - - // independent from second signer - {false, 1, set2, set1}, // sig must match - {true, 1, set2, set2}, // seq of set2 independent from set1 - {true, 2, set2, set321}, // extra sigs don't change the situation - - // multisig has same requirements - {false, 0, set12, set12}, // need valid sequence number - {false, 1, set12, set2}, // they all must sign - {true, 1, set12, set12}, // this is proper, independent of act1 and act2 - {true, 2, set21, set21}, // order of actors doesn't matter - {false, 2, set12, set12}, // but can't repeat sequence - {true, 3, set12, set321}, // no effect from extra sigs - - // triple sigs also work - {false, 2, set123, set123}, // must start with seq=1 - {false, 1, set123, set12}, // all must sign - {true, 1, set123, set321}, // this works - {true, 2, set321, set321}, // other order is the same - {false, 2, set321, set321}, // no repetition - - // signers with different chain-IDs and apps from actors - {false, 3, set123, set123Chain2}, // sign with different chain actors - {false, 3, set123, set123App2}, // sign with different app actors - {false, 3, set123, set123MixedChains}, // sign with mixed chain actor - {false, 3, set123, set123MixedApps}, // sign with mixed app actors - - // signers from different chain-IDs and apps, working - {true, 1, set123Chain2, set123Chain2}, - {true, 1, set123App2, set123App2}, - {true, 1, set123MixedChains, set123MixedChains}, - {true, 1, set123MixedApps, set123MixedApps}, - } - - raw := stack.NewRawTx([]byte{42}) - for i, test := range testList { - - // set the permissions - myCtx := ctx.WithPermissions(test.signers...) - - tx := NewTx(test.seq, test.actors, raw) - nonceTx, ok := tx.Unwrap().(Tx) - require.True(ok) - - err := nonceTx.CheckIncrementSeq(myCtx, store) - if test.valid { - assert.Nil(err, "%d: %+v", i, err) - } else { - assert.NotNil(err, "%d", i) - } - } - -} diff --git a/x/_attic/recover/recovery.go b/x/_attic/recover/recovery.go deleted file mode 100644 index 599b292a6..000000000 --- a/x/_attic/recover/recovery.go +++ /dev/null @@ -1,46 +0,0 @@ -package util - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/errors" -) - -// Recovery catches any panics and returns them as errors instead -type Recovery struct{} - -var _ sdk.Decorator = Recovery{} - -// CheckTx catches any panic and converts to error - fulfills Middlware interface -func (Recovery) CheckTx(ctx sdk.Context, store sdk.SimpleDB, - tx interface{}, next sdk.Checker) (res sdk.CheckResult, err error) { - - defer func() { - if r := recover(); r != nil { - err = normalizePanic(r) - } - }() - return next.CheckTx(ctx, store, tx) -} - -// DeliverTx catches any panic and converts to error - fulfills Middlware interface -func (Recovery) DeliverTx(ctx sdk.Context, store sdk.SimpleDB, - tx interface{}, next sdk.Deliverer) (res sdk.DeliverResult, err error) { - - defer func() { - if r := recover(); r != nil { - err = normalizePanic(r) - } - }() - return next.DeliverTx(ctx, store, tx) -} - -// normalizePanic makes sure we can get a nice TMError (with stack) out of it -func normalizePanic(p interface{}) error { - if err, isErr := p.(error); isErr { - return errors.Wrap(err) - } - msg := fmt.Sprintf("%v", p) - return errors.ErrInternal(msg) -} diff --git a/x/_attic/recover/recovery_test.go b/x/_attic/recover/recovery_test.go deleted file mode 100644 index 4a3dc0c54..000000000 --- a/x/_attic/recover/recovery_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package util - -import ( - "errors" - "strconv" - "testing" - - "github.com/stretchr/testify/assert" - - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/state" -) - -func TestRecovery(t *testing.T) { - assert := assert.New(t) - - // generic args here... - ctx := MockContext("test-chain", 20) - store := state.NewMemKVStore() - tx := 0 // we ignore it, so it can be anything - - cases := []struct { - msg string // what to send to panic - err error // what to send to panic - expected string // expected text in panic - }{ - {"buzz", nil, "buzz"}, - {"", errors.New("some text"), "some text"}, - {"text", errors.New("error"), "error"}, - } - - for idx, tc := range cases { - i := strconv.Itoa(idx) - fail := PanicHandler{Msg: tc.msg, Err: tc.err} - rec := Recovery{} - app := sdk.ChainDecorators(rec).WithHandler(fail) - - // make sure check returns error, not a panic crash - _, err := app.CheckTx(ctx, store, tx) - if assert.NotNil(err, i) { - assert.Equal(tc.expected, err.Error(), i) - } - - // make sure deliver returns error, not a panic crash - _, err = app.DeliverTx(ctx, store, tx) - if assert.NotNil(err, i) { - assert.Equal(tc.expected, err.Error(), i) - } - - } -}