Bare auth
This commit is contained in:
parent
83b43f3378
commit
fdc7834dae
|
@ -1,37 +1,23 @@
|
||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
crypto "github.com/tendermint/go-crypto"
|
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk"
|
sdk "github.com/cosmos/cosmos-sdk"
|
||||||
"github.com/cosmos/cosmos-sdk/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//nolint
|
type CheckSignatures struct{}
|
||||||
const (
|
|
||||||
NameSigs = "sigs"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Signatures parses out go-crypto signatures and adds permissions to the
|
var _ sdk.Decorator = CheckSignatures{}
|
||||||
// context for use inside the application
|
|
||||||
type Signatures struct{}
|
|
||||||
|
|
||||||
var _ sdk.Decorator = Signatures{}
|
|
||||||
|
|
||||||
// SigPerm takes the binary address from PubKey.Address and makes it an Actor
|
|
||||||
func SigPerm(addr []byte) sdk.Actor {
|
|
||||||
return sdk.NewActor(NameSigs, addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckTx verifies the signatures are correct - fulfills Middlware interface
|
// CheckTx verifies the signatures are correct - fulfills Middlware interface
|
||||||
func (Signatures) CheckTx(ctx sdk.Context, store sdk.SimpleDB,
|
func (Signatures) CheckTx(ctx sdk.Context, store sdk.SimpleDB,
|
||||||
tx interface{}, next sdk.Checker) (res sdk.CheckResult, err error) {
|
tx interface{}, next sdk.Checker) (res sdk.CheckResult, err error) {
|
||||||
|
|
||||||
sigs, err := getSigners(tx)
|
// Check that signatures match
|
||||||
if err != nil {
|
// TODO
|
||||||
return res, err
|
|
||||||
}
|
// Add info to context
|
||||||
ctx2 := addSigners(ctx, sigs)
|
// TODO
|
||||||
|
|
||||||
return next.CheckTx(ctx2, store, tx)
|
return next.CheckTx(ctx2, store, tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,28 +25,11 @@ func (Signatures) CheckTx(ctx sdk.Context, store sdk.SimpleDB,
|
||||||
func (Signatures) DeliverTx(ctx sdk.Context, store sdk.SimpleDB,
|
func (Signatures) DeliverTx(ctx sdk.Context, store sdk.SimpleDB,
|
||||||
tx interface{}, next sdk.Deliverer) (res sdk.DeliverResult, err error) {
|
tx interface{}, next sdk.Deliverer) (res sdk.DeliverResult, err error) {
|
||||||
|
|
||||||
sigs, err := getSigners(tx)
|
// Check that signatures match
|
||||||
if err != nil {
|
// TODO
|
||||||
return res, err
|
|
||||||
}
|
// Add info to context
|
||||||
ctx2 := addSigners(ctx, sigs)
|
// TODO
|
||||||
|
|
||||||
return next.DeliverTx(ctx2, store, tx)
|
return next.DeliverTx(ctx2, store, tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addSigners(ctx sdk.Context, sigs []crypto.PubKey) sdk.Context {
|
|
||||||
perms := make([]sdk.Actor, len(sigs))
|
|
||||||
for i, s := range sigs {
|
|
||||||
perms[i] = SigPerm(s.Address())
|
|
||||||
}
|
|
||||||
// add the signers to the context and continue
|
|
||||||
return ctx.WithPermissions(perms...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSigners(tx interface{}) ([]crypto.PubKey, error) {
|
|
||||||
stx, ok := tx.(Signable)
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.ErrUnauthorized()
|
|
||||||
}
|
|
||||||
sig, err := stx.Signers()
|
|
||||||
return sig, err
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
package auth
|
|
||||||
|
|
||||||
import (
|
|
||||||
crypto "github.com/tendermint/go-crypto"
|
|
||||||
"github.com/tendermint/go-crypto/keys"
|
|
||||||
wire "github.com/tendermint/go-wire"
|
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk"
|
|
||||||
"github.com/cosmos/cosmos-sdk/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
type oneSig struct {
|
|
||||||
// Data is the payload
|
|
||||||
Data util.RawTx
|
|
||||||
// NamedSig holds credentials and exposes Sign
|
|
||||||
*NamedSig
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ Signable = oneSig{}
|
|
||||||
var _ sdk.Msg = oneSig{}
|
|
||||||
var _ keys.Signable = oneSig{}
|
|
||||||
|
|
||||||
func (o oneSig) SignBytes() []byte {
|
|
||||||
return wire.BinaryBytes(o.Data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o oneSig) TxBytes() ([]byte, error) {
|
|
||||||
// if o.NamedSig.Empty() {
|
|
||||||
// return nil, errors.ErrMissingSignature()
|
|
||||||
// }
|
|
||||||
return wire.BinaryBytes(o), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o oneSig) Signers() ([]crypto.PubKey, error) {
|
|
||||||
return o.NamedSig.Signers(o.SignBytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o oneSig) GetTx() interface{} {
|
|
||||||
return o.Data
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSingle(data []byte) oneSig {
|
|
||||||
return oneSig{
|
|
||||||
Data: util.NewRawTx(data),
|
|
||||||
NamedSig: NewSig(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type multiSig struct {
|
|
||||||
// Data is the payload
|
|
||||||
Data util.RawTx
|
|
||||||
// NamedSig holds credentials and exposes Sign
|
|
||||||
*NamedSigs
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ Signable = oneSig{}
|
|
||||||
var _ sdk.Msg = oneSig{}
|
|
||||||
var _ keys.Signable = oneSig{}
|
|
||||||
|
|
||||||
func (m multiSig) SignBytes() []byte {
|
|
||||||
return wire.BinaryBytes(m.Data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m multiSig) TxBytes() ([]byte, error) {
|
|
||||||
// if m.NamedSigs.Empty() {
|
|
||||||
// return nil, errors.ErrMissingSignature()
|
|
||||||
// }
|
|
||||||
return wire.BinaryBytes(m), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m multiSig) Signers() ([]crypto.PubKey, error) {
|
|
||||||
return m.NamedSigs.Signers(m.SignBytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m multiSig) GetTx() interface{} {
|
|
||||||
return m.Data
|
|
||||||
}
|
|
||||||
|
|
||||||
func newMulti(data []byte) multiSig {
|
|
||||||
return multiSig{
|
|
||||||
Data: util.NewRawTx(data),
|
|
||||||
NamedSigs: NewMultiSig(),
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,97 +0,0 @@
|
||||||
package auth
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
|
|
||||||
crypto "github.com/tendermint/go-crypto"
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
// 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())
|
|
||||||
|
|
||||||
// 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},
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
|
|
||||||
// make the stack check for the given permission
|
|
||||||
app := sdk.ChainDecorators(
|
|
||||||
Signatures{},
|
|
||||||
util.CheckDecorator{Required: tc.check},
|
|
||||||
).WithHandler(
|
|
||||||
util.OKHandler{},
|
|
||||||
)
|
|
||||||
|
|
||||||
var tx interface{}
|
|
||||||
// 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
|
|
||||||
} else {
|
|
||||||
otx := newSingle(raw)
|
|
||||||
for _, k := range tc.keys {
|
|
||||||
err := Sign(otx, k)
|
|
||||||
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.DeliverTx(ctx, store, tx)
|
|
||||||
if tc.valid {
|
|
||||||
assert.Nil(err, "%d: %+v", i, err)
|
|
||||||
} else {
|
|
||||||
assert.NotNil(err, idx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import crypto "github.com/tendermint/go-crypto"
|
||||||
|
|
||||||
|
type Account interface {
|
||||||
|
Get(key interface{}) (value interface{})
|
||||||
|
|
||||||
|
Address() []byte
|
||||||
|
PubKey() crypto.PubKey
|
||||||
|
}
|
||||||
|
|
||||||
|
type AccountStore interface {
|
||||||
|
GetAccount(addr []byte) Account
|
||||||
|
SetAccount(acc Account)
|
||||||
|
}
|
Loading…
Reference in New Issue