From d2ed8c8871de72655a44de08df1e74c9b9d504b7 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 24 Oct 2017 16:56:16 +0200 Subject: [PATCH] More functioning auth tests --- modules/auth/helpers_test.go | 4 +- modules/auth/signature_test.go | 162 ++++++++++++++++----------------- modules/auth/tx.go | 1 - modules/auth/tx_test.go | 4 +- util/decorators.go | 53 +++++++++++ 5 files changed, 138 insertions(+), 86 deletions(-) create mode 100644 util/decorators.go diff --git a/modules/auth/helpers_test.go b/modules/auth/helpers_test.go index 3c1cc0e01..90f343037 100644 --- a/modules/auth/helpers_test.go +++ b/modules/auth/helpers_test.go @@ -39,7 +39,7 @@ func (o oneSig) GetTx() interface{} { return o.Data } -func OneSig(data []byte) keys.Signable { +func newSingle(data []byte) oneSig { return oneSig{ Data: util.NewRawTx(data), NamedSig: NewSig(), @@ -76,7 +76,7 @@ func (m multiSig) GetTx() interface{} { return m.Data } -func MultiSig(data []byte) keys.Signable { +func newMulti(data []byte) multiSig { return multiSig{ Data: util.NewRawTx(data), NamedSigs: NewMultiSig(), diff --git a/modules/auth/signature_test.go b/modules/auth/signature_test.go index a6411a09f..fedb76cef 100644 --- a/modules/auth/signature_test.go +++ b/modules/auth/signature_test.go @@ -1,97 +1,97 @@ package auth -// import ( -// "strconv" -// "testing" +import ( + "strconv" + "testing" -// "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/assert" -// crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/go-crypto" -// sdk "github.com/cosmos/cosmos-sdk" -// "github.com/cosmos/cosmos-sdk/state" -// "github.com/cosmos/cosmos-sdk/util" -// ) + sdk "github.com/cosmos/cosmos-sdk" + "github.com/cosmos/cosmos-sdk/state" + "github.com/cosmos/cosmos-sdk/util" +) -// func TestSignatureChecks(t *testing.T) { -// assert := assert.New(t) +func TestSignatureChecks(t *testing.T) { + assert := assert.New(t) -// // generic args -// ctx := util.MockContext("test-chain", 100) -// store := state.NewMemKVStore() -// raw := util.NewRawTx([]byte{1, 2, 3, 4}) + // generic args + ctx := util.MockContext("test-chain", 100) + store := state.NewMemKVStore() + raw := []byte{1, 2, 3, 4} -// // let's make some keys.... -// priv1 := crypto.GenPrivKeyEd25519().Wrap() -// actor1 := SigPerm(priv1.PubKey().Address()) -// priv2 := crypto.GenPrivKeySecp256k1().Wrap() -// actor2 := SigPerm(priv2.PubKey().Address()) + // let's make some keys.... + priv1 := crypto.GenPrivKeyEd25519().Wrap() + actor1 := SigPerm(priv1.PubKey().Address()) + priv2 := crypto.GenPrivKeySecp256k1().Wrap() + actor2 := SigPerm(priv2.PubKey().Address()) -// // test cases to make sure signature checks are solid -// cases := []struct { -// useMultiSig bool -// keys []crypto.PrivKey -// check sdk.Actor -// valid bool -// }{ -// // test with single sigs -// {false, []crypto.PrivKey{priv1}, actor1, true}, -// {false, []crypto.PrivKey{priv1}, actor2, false}, -// {false, []crypto.PrivKey{priv2}, actor2, true}, -// {false, []crypto.PrivKey{}, actor2, false}, + // test cases to make sure signature checks are solid + cases := []struct { + useMultiSig bool + keys []crypto.PrivKey + check sdk.Actor + valid bool + }{ + // test with single sigs + {false, []crypto.PrivKey{priv1}, actor1, true}, + {false, []crypto.PrivKey{priv1}, actor2, false}, + {false, []crypto.PrivKey{priv2}, actor2, true}, + {false, []crypto.PrivKey{}, actor2, false}, -// // same with multi sigs -// {true, []crypto.PrivKey{priv1}, actor1, true}, -// {true, []crypto.PrivKey{priv1}, actor2, false}, -// {true, []crypto.PrivKey{priv2}, actor2, true}, -// {true, []crypto.PrivKey{}, actor2, false}, + // same with multi sigs + {true, []crypto.PrivKey{priv1}, actor1, true}, + {true, []crypto.PrivKey{priv1}, actor2, false}, + {true, []crypto.PrivKey{priv2}, actor2, true}, + {true, []crypto.PrivKey{}, actor2, false}, -// // make sure both match on a multisig -// {true, []crypto.PrivKey{priv1, priv2}, actor1, true}, -// {true, []crypto.PrivKey{priv1, priv2}, actor2, true}, -// } + // make sure both match on a multisig + {true, []crypto.PrivKey{priv1, priv2}, actor1, true}, + {true, []crypto.PrivKey{priv1, priv2}, actor2, true}, + } -// for i, tc := range cases { -// idx := strconv.Itoa(i) + for i, tc := range cases { + idx := strconv.Itoa(i) -// // make the stack check for the given permission -// app := sdk.ChainDecorators( -// Signatures{}, -// util.CheckMiddleware{Required: tc.check}, -// ).WithHandler( -// util.OKHandler{}, -// ) + // make the stack check for the given permission + app := sdk.ChainDecorators( + Signatures{}, + util.CheckDecorator{Required: tc.check}, + ).WithHandler( + util.OKHandler{}, + ) -// var tx sdk.Tx -// // this does the signing as needed -// if tc.useMultiSig { -// mtx := NewMulti(raw) -// for _, k := range tc.keys { -// err := Sign(mtx, k) -// assert.Nil(err, "%d: %+v", i, err) -// } -// tx = mtx.Wrap() -// } else { -// otx := NewSig(raw) -// for _, k := range tc.keys { -// err := Sign(otx, k) -// assert.Nil(err, "%d: %+v", i, err) -// } -// tx = otx.Wrap() -// } + var tx interface{} + // this does the signing as needed + if tc.useMultiSig { + mtx := newMulti(raw) + for _, k := range tc.keys { + err := Sign(mtx.SignBytes(), k, mtx.NamedSigs) + assert.Nil(err, "%d: %+v", i, err) + } + tx = mtx + } else { + otx := newSingle(raw) + for _, k := range tc.keys { + err := Sign(otx.SignBytes(), k, otx.NamedSig) + assert.Nil(err, "%d: %+v", i, err) + } + tx = otx + } -// _, err := app.CheckTx(ctx, store, tx) -// if tc.valid { -// assert.Nil(err, "%d: %+v", i, err) -// } else { -// assert.NotNil(err, idx) -// } + _, err := app.CheckTx(ctx, store, tx) + if tc.valid { + assert.Nil(err, "%d: %+v", i, err) + } else { + assert.NotNil(err, idx) + } -// _, err = app.DeliverTx(ctx, store, tx) -// if tc.valid { -// assert.Nil(err, "%d: %+v", i, err) -// } else { -// assert.NotNil(err, idx) -// } -// } -// } + _, err = app.DeliverTx(ctx, store, tx) + if tc.valid { + assert.Nil(err, "%d: %+v", i, err) + } else { + assert.NotNil(err, idx) + } + } +} diff --git a/modules/auth/tx.go b/modules/auth/tx.go index a25bb6321..1302f0e3b 100644 --- a/modules/auth/tx.go +++ b/modules/auth/tx.go @@ -25,7 +25,6 @@ import ( // Credential can be combined with message data // to create a keys.Signable type Credential interface { - Empty() bool Sign(pubkey crypto.PubKey, sig crypto.Signature) error Signers(signBytes []byte) ([]crypto.PubKey, error) } diff --git a/modules/auth/tx_test.go b/modules/auth/tx_test.go index 6fe3c3b96..a7c9ffc0e 100644 --- a/modules/auth/tx_test.go +++ b/modules/auth/tx_test.go @@ -52,7 +52,7 @@ func TestOneSig(t *testing.T) { } for _, tc := range cases { - tx := OneSig([]byte(tc.data)) + tx := newSingle([]byte(tc.data)) // unsigned version _, err = tx.Signers() assert.NotNil(err) @@ -117,7 +117,7 @@ func TestMultiSig(t *testing.T) { } for _, tc := range cases { - tx := MultiSig([]byte(tc.data)) + tx := newMulti([]byte(tc.data)) // unsigned version _, err = tx.Signers() assert.NotNil(err) diff --git a/util/decorators.go b/util/decorators.go new file mode 100644 index 000000000..e9d9bd94d --- /dev/null +++ b/util/decorators.go @@ -0,0 +1,53 @@ +package util + +import ( + sdk "github.com/cosmos/cosmos-sdk" + "github.com/cosmos/cosmos-sdk/errors" +) + +// CheckDecorator returns an error if the tx doesn't have auth of this +// Required Actor, otherwise passes along the call untouched +type CheckDecorator struct { + Required sdk.Actor +} + +var _ sdk.Decorator = CheckDecorator{} + +func (p CheckDecorator) CheckTx(ctx sdk.Context, store sdk.SimpleDB, + tx interface{}, next sdk.Checker) (res sdk.CheckResult, err error) { + + if !ctx.HasPermission(p.Required) { + return res, errors.ErrUnauthorized() + } + return next.CheckTx(ctx, store, tx) +} + +func (p CheckDecorator) DeliverTx(ctx sdk.Context, store sdk.SimpleDB, + tx interface{}, next sdk.Deliverer) (res sdk.DeliverResult, err error) { + + if !ctx.HasPermission(p.Required) { + return res, errors.ErrUnauthorized() + } + return next.DeliverTx(ctx, store, tx) +} + +// GrantDecorator tries to set the permission to this Actor, which may be prohibited +type GrantDecorator struct { + Auth sdk.Actor +} + +var _ sdk.Decorator = GrantDecorator{} + +func (g GrantDecorator) CheckTx(ctx sdk.Context, store sdk.SimpleDB, + tx interface{}, next sdk.Checker) (res sdk.CheckResult, err error) { + + ctx = ctx.WithPermissions(g.Auth) + return next.CheckTx(ctx, store, tx) +} + +func (g GrantDecorator) DeliverTx(ctx sdk.Context, store sdk.SimpleDB, + tx interface{}, next sdk.Deliverer) (res sdk.DeliverResult, err error) { + + ctx = ctx.WithPermissions(g.Auth) + return next.DeliverTx(ctx, store, tx) +}