Moved content of txs package to sit next to the handlers

This commit is contained in:
Ethan Frey 2017-07-06 16:33:38 +02:00
parent a047e210fa
commit b757467f7b
18 changed files with 169 additions and 159 deletions

View File

@ -11,9 +11,9 @@ import (
abci "github.com/tendermint/abci/types"
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/modules/auth"
"github.com/tendermint/basecoin/modules/base"
"github.com/tendermint/basecoin/modules/coin"
"github.com/tendermint/basecoin/state"
"github.com/tendermint/basecoin/txs"
wire "github.com/tendermint/go-wire"
eyes "github.com/tendermint/merkleeyes/client"
"github.com/tendermint/tmlibs/log"
@ -44,9 +44,9 @@ func (at *appTest) getTx(seq int, coins coin.Coins) basecoin.Tx {
in := []coin.TxInput{{Address: at.acctIn.Actor(), Coins: coins, Sequence: seq}}
out := []coin.TxOutput{{Address: at.acctOut.Actor(), Coins: coins}}
tx := coin.NewSendTx(in, out)
tx = txs.NewChain(at.chainID, tx)
stx := txs.NewMulti(tx)
txs.Sign(stx, at.acctIn.Key)
tx = base.NewChainTx(at.chainID, tx)
stx := auth.NewMulti(tx)
auth.Sign(stx, at.acctIn.Key)
return stx.Wrap()
}

View File

@ -14,8 +14,8 @@ import (
cmn "github.com/tendermint/tmlibs/common"
"github.com/tendermint/basecoin/modules/auth"
"github.com/tendermint/basecoin/modules/base"
"github.com/tendermint/basecoin/modules/coin"
"github.com/tendermint/basecoin/txs"
)
//-------------------------
@ -63,8 +63,8 @@ func doSendTx(cmd *cobra.Command, args []string) error {
// TODO: make this more flexible for middleware
// add the chain info
tx = txs.NewChain(commands.GetChainID(), tx)
stx := txs.NewSig(tx)
tx = base.NewChainTx(commands.GetChainID(), tx)
stx := auth.NewSig(tx)
// Sign if needed and post. This it the work-horse
bres, err := txcmd.SignAndPostTx(stx)

View File

@ -9,8 +9,9 @@ import (
txcmd "github.com/tendermint/light-client/commands/txs"
"github.com/tendermint/basecoin/docs/guide/counter/plugins/counter"
"github.com/tendermint/basecoin/modules/auth"
"github.com/tendermint/basecoin/modules/base"
"github.com/tendermint/basecoin/modules/coin"
"github.com/tendermint/basecoin/txs"
)
//CounterTxCmd is the CLI command to execute the counter
@ -56,8 +57,8 @@ func counterTx(cmd *cobra.Command, args []string) error {
// TODO: make this more flexible for middleware
// add the chain info
tx = txs.NewChain(commands.GetChainID(), tx)
stx := txs.NewSig(tx)
tx = base.NewChainTx(commands.GetChainID(), tx)
stx := auth.NewSig(tx)
// Sign if needed and post. This it the work-horse
bres, err := txcmd.SignAndPostTx(stx)

View File

@ -8,8 +8,9 @@ import (
"github.com/stretchr/testify/require"
abci "github.com/tendermint/abci/types"
"github.com/tendermint/basecoin/app"
"github.com/tendermint/basecoin/modules/auth"
"github.com/tendermint/basecoin/modules/base"
"github.com/tendermint/basecoin/modules/coin"
"github.com/tendermint/basecoin/txs"
"github.com/tendermint/go-wire"
eyescli "github.com/tendermint/merkleeyes/client"
"github.com/tendermint/tmlibs/log"
@ -41,9 +42,9 @@ func TestCounterPlugin(t *testing.T) {
// Deliver a CounterTx
DeliverCounterTx := func(valid bool, counterFee coin.Coins, inputSequence int) abci.Result {
tx := NewTx(valid, counterFee, inputSequence)
tx = txs.NewChain(chainID, tx)
stx := txs.NewSig(tx)
txs.Sign(stx, acct.Key)
tx = base.NewChainTx(chainID, tx)
stx := auth.NewSig(tx)
auth.Sign(stx, acct.Key)
txBytes := wire.BinaryBytes(stx.Wrap())
return bcApp.DeliverTx(txBytes)
}

View File

@ -32,8 +32,8 @@ func SigPerm(addr []byte) basecoin.Actor {
return basecoin.NewActor(NameSigs, addr)
}
// Signed allows us to use txs.OneSig and txs.MultiSig (and others??)
type Signed interface {
// Signable allows us to use txs.OneSig and txs.MultiSig (and others??)
type Signable interface {
basecoin.TxLayer
Signers() ([]crypto.PubKey, error)
}
@ -68,7 +68,7 @@ func addSigners(ctx basecoin.Context, sigs []crypto.PubKey) basecoin.Context {
}
func getSigners(tx basecoin.Tx) ([]crypto.PubKey, basecoin.Tx, error) {
stx, ok := tx.Unwrap().(Signed)
stx, ok := tx.Unwrap().(Signable)
if !ok {
return nil, basecoin.Tx{}, errors.ErrUnauthorized()
}

View File

@ -12,7 +12,6 @@ import (
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/stack"
"github.com/tendermint/basecoin/state"
"github.com/tendermint/basecoin/txs"
)
func TestSignatureChecks(t *testing.T) {
@ -21,7 +20,7 @@ func TestSignatureChecks(t *testing.T) {
// generic args
ctx := stack.NewContext("test-chain", log.NewNopLogger())
store := state.NewMemKVStore()
raw := txs.NewRaw([]byte{1, 2, 3, 4})
raw := stack.NewRawTx([]byte{1, 2, 3, 4})
// let's make some keys....
priv1 := crypto.GenPrivKeyEd25519().Wrap()
@ -65,16 +64,16 @@ func TestSignatureChecks(t *testing.T) {
var tx basecoin.Tx
// this does the signing as needed
if tc.useMultiSig {
mtx := txs.NewMulti(raw)
mtx := NewMulti(raw)
for _, k := range tc.keys {
err := txs.Sign(mtx, k)
err := Sign(mtx, k)
assert.Nil(err, "%d: %+v", i, err)
}
tx = mtx.Wrap()
} else {
otx := txs.NewSig(raw)
otx := NewSig(raw)
for _, k := range tc.keys {
err := txs.Sign(otx, k)
err := Sign(otx, k)
assert.Nil(err, "%d: %+v", i, err)
}
tx = otx.Wrap()

View File

@ -1,5 +1,5 @@
/*
package tx contains generic Signable implementations that can be used
package auth contains generic Signable implementations that can be used
by your application or tests to handle authentication needs.
It currently supports transaction data as opaque bytes and either single
@ -11,7 +11,7 @@ You can create them with NewSig() and NewMultiSig(), and they fulfill
the keys.Signable interface. You can then .Wrap() them to create
a basecoin.Tx.
*/
package txs
package auth
import (
crypto "github.com/tendermint/go-crypto"
@ -22,12 +22,27 @@ import (
"github.com/tendermint/basecoin/errors"
)
// nolint
const (
// for signatures
ByteSingleTx = 0x16
ByteMultiSig = 0x17
)
// nolint
const (
// for signatures
TypeSingleTx = NameSigs + "/one"
TypeMultiSig = NameSigs + "/multi"
)
// Signed holds one signature of the data
type Signed struct {
Sig crypto.Signature
Pubkey crypto.PubKey
}
// Empty returns true if there is not enough signature info
func (s Signed) Empty() bool {
return s.Sig.Empty() || s.Pubkey.Empty()
}
@ -36,7 +51,7 @@ func (s Signed) Empty() bool {
func init() {
basecoin.TxMapper.
RegisterImplementation(&OneSig{}, TypeSig, ByteSig).
RegisterImplementation(&OneSig{}, TypeSingleTx, ByteSingleTx).
RegisterImplementation(&MultiSig{}, TypeMultiSig, ByteMultiSig)
}
@ -51,6 +66,7 @@ type OneSig struct {
var _ keys.Signable = &OneSig{}
var _ basecoin.TxLayer = &OneSig{}
// NewSig wraps the tx with a Signable that accepts exactly one signature
func NewSig(tx basecoin.Tx) *OneSig {
return &OneSig{Tx: tx}
}
@ -122,6 +138,7 @@ type MultiSig struct {
var _ keys.Signable = &MultiSig{}
var _ basecoin.TxLayer = &MultiSig{}
// NewMulti wraps the tx with a Signable that accepts arbitrary numbers of signatures
func NewMulti(tx basecoin.Tx) *MultiSig {
return &MultiSig{Tx: tx}
}

View File

@ -1,4 +1,4 @@
package txs
package auth
import (
"testing"
@ -6,6 +6,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/basecoin/stack"
crypto "github.com/tendermint/go-crypto"
keys "github.com/tendermint/go-crypto/keys"
"github.com/tendermint/go-crypto/keys/cryptostore"
@ -22,7 +23,7 @@ func checkSignBytes(t *testing.T, bytes []byte, expected string) {
require.Nil(t, err)
// now make sure this tx is data.Bytes with the info we want
raw, ok := preTx.Unwrap().(Raw)
raw, ok := preTx.Unwrap().(stack.RawTx)
require.True(t, ok)
assert.Equal(t, expected, string(raw.Bytes))
}
@ -55,7 +56,7 @@ func TestOneSig(t *testing.T) {
}
for _, tc := range cases {
inner := NewRaw([]byte(tc.data)).Wrap()
inner := stack.NewRawTx([]byte(tc.data)).Wrap()
tx := NewSig(inner)
// unsigned version
_, err = tx.Signers()
@ -121,7 +122,7 @@ func TestMultiSig(t *testing.T) {
}
for _, tc := range cases {
inner := NewRaw([]byte(tc.data)).Wrap()
inner := stack.NewRawTx([]byte(tc.data)).Wrap()
tx := NewMulti(inner)
// unsigned version
_, err = tx.Signers()

View File

@ -5,12 +5,11 @@ import (
"github.com/tendermint/basecoin/errors"
"github.com/tendermint/basecoin/stack"
"github.com/tendermint/basecoin/state"
"github.com/tendermint/basecoin/txs"
)
//nolint
const (
NameChain = "chan"
NameChain = "chain"
)
// Chain enforces that this tx was bound to the named chain
@ -43,9 +42,9 @@ func (c Chain) DeliverTx(ctx basecoin.Context, store state.KVStore, tx basecoin.
return next.DeliverTx(ctx, store, stx)
}
// checkChain makes sure the tx is a txs.Chain and
// checkChain makes sure the tx is a Chain Tx and is on the proper chain
func (c Chain) checkChain(chainID string, tx basecoin.Tx) (basecoin.Tx, error) {
ctx, ok := tx.Unwrap().(*txs.Chain)
ctx, ok := tx.Unwrap().(ChainTx)
if !ok {
return tx, errors.ErrNoChain()
}

View File

@ -11,7 +11,6 @@ import (
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/stack"
"github.com/tendermint/basecoin/state"
"github.com/tendermint/basecoin/txs"
)
func TestChain(t *testing.T) {
@ -19,14 +18,14 @@ func TestChain(t *testing.T) {
msg := "got it"
chainID := "my-chain"
raw := txs.NewRaw([]byte{1, 2, 3, 4})
raw := stack.NewRawTx([]byte{1, 2, 3, 4})
cases := []struct {
tx basecoin.Tx
valid bool
errorMsg string
}{
{txs.NewChain(chainID, raw), true, ""},
{txs.NewChain("someone-else", raw), false, "someone-else"},
{NewChainTx(chainID, raw), true, ""},
{NewChainTx("someone-else", raw), false, "someone-else"},
{raw, false, "No chain id provided"},
}

View File

@ -9,7 +9,6 @@ import (
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/stack"
"github.com/tendermint/basecoin/state"
"github.com/tendermint/basecoin/txs"
)
//nolint
@ -31,7 +30,7 @@ var _ stack.Middleware = Multiplexer{}
// CheckTx splits the input tx and checks them all - fulfills Middlware interface
func (Multiplexer) CheckTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx, next basecoin.Checker) (res basecoin.Result, err error) {
if mtx, ok := tx.Unwrap().(*txs.MultiTx); ok {
if mtx, ok := tx.Unwrap().(*MultiTx); ok {
return runAll(ctx, store, mtx.Txs, next.CheckTx)
}
return next.CheckTx(ctx, store, tx)
@ -39,7 +38,7 @@ func (Multiplexer) CheckTx(ctx basecoin.Context, store state.KVStore, tx basecoi
// DeliverTx splits the input tx and checks them all - fulfills Middlware interface
func (Multiplexer) DeliverTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx, next basecoin.Deliver) (res basecoin.Result, err error) {
if mtx, ok := tx.Unwrap().(*txs.MultiTx); ok {
if mtx, ok := tx.Unwrap().(*MultiTx); ok {
return runAll(ctx, store, mtx.Txs, next.DeliverTx)
}
return next.DeliverTx(ctx, store, tx)

66
modules/base/tx.go Normal file
View File

@ -0,0 +1,66 @@
package base
import "github.com/tendermint/basecoin"
// nolint
const (
// for utils...
ByteMultiTx = 0x2
ByteChainTx = 0x3
)
//nolint
const (
TypeMultiTx = NameMultiplexer + "/tx"
TypeChainTx = NameChain + "/tx"
)
func init() {
basecoin.TxMapper.
RegisterImplementation(MultiTx{}, TypeMultiTx, ByteMultiTx).
RegisterImplementation(ChainTx{}, TypeChainTx, ByteChainTx)
}
/**** MultiTx ******/
type MultiTx struct {
Txs []basecoin.Tx `json:"txs"`
}
func NewMultiTx(txs ...basecoin.Tx) basecoin.Tx {
return (MultiTx{Txs: txs}).Wrap()
}
func (mt MultiTx) Wrap() basecoin.Tx {
return basecoin.Tx{mt}
}
func (mt MultiTx) ValidateBasic() error {
for _, t := range mt.Txs {
err := t.ValidateBasic()
if err != nil {
return err
}
}
return nil
}
/*** ChainTx ****/
// ChainTx locks this tx to one chainTx, wrap with this before signing
type ChainTx struct {
Tx basecoin.Tx `json:"tx"`
ChainID string `json:"chain_id"`
}
func NewChainTx(chainID string, tx basecoin.Tx) basecoin.Tx {
return (ChainTx{Tx: tx, ChainID: chainID}).Wrap()
}
func (c ChainTx) Wrap() basecoin.Tx {
return basecoin.Tx{c}
}
func (c ChainTx) ValidateBasic() error {
// TODO: more checks? chainID?
return c.Tx.ValidateBasic()
}

View File

@ -1,4 +1,4 @@
package txs
package base
import (
"strconv"
@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/basecoin/stack"
"github.com/tendermint/go-wire/data"
"github.com/tendermint/basecoin"
@ -16,15 +17,15 @@ func TestEncoding(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
raw := NewRaw([]byte{0x34, 0xa7})
raw2 := NewRaw([]byte{0x73, 0x86, 0x22})
raw := stack.NewRawTx([]byte{0x34, 0xa7})
raw2 := stack.NewRawTx([]byte{0x73, 0x86, 0x22})
cases := []struct {
Tx basecoin.Tx
}{
{raw},
{NewMultiTx(raw, raw2)},
{NewChain("foobar", raw)},
{NewChainTx("foobar", raw)},
}
for idx, tc := range cases {

View File

@ -1,14 +1,14 @@
package stack
import (
"github.com/pkg/errors"
"github.com/tendermint/go-wire/data"
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/errors"
"github.com/tendermint/basecoin/state"
)
//nolint
const (
NameOK = "ok"
NameFail = "fail"
@ -16,6 +16,38 @@ const (
NameEcho = "echo"
)
//nolint
const (
ByteRawTx = 0x1
TypeRawTx = "raw"
rawMaxSize = 2000 * 1000
)
func init() {
basecoin.TxMapper.
RegisterImplementation(RawTx{}, TypeRawTx, ByteRawTx)
}
// RawTx just contains bytes that can be hex-ified
type RawTx struct {
data.Bytes
}
func (r RawTx) Wrap() basecoin.Tx {
return basecoin.Tx{r}
}
func (r RawTx) ValidateBasic() error {
if len(r.Bytes) > rawMaxSize {
return errors.ErrTooLarge()
}
return nil
}
func NewRawTx(d []byte) basecoin.Tx {
return RawTx{data.Bytes(d)}.Wrap()
}
// OKHandler just used to return okay to everything
type OKHandler struct {
Log string
@ -75,12 +107,12 @@ func (_ FailHandler) Name() string {
// CheckTx always returns the given error
func (f FailHandler) CheckTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
return res, errors.WithStack(f.Err)
return res, errors.Wrap(f.Err)
}
// DeliverTx always returns the given error
func (f FailHandler) DeliverTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
return res, errors.WithStack(f.Err)
return res, errors.Wrap(f.Err)
}
// PanicHandler always panics, using the given error (first choice) or msg (fallback)

View File

@ -12,7 +12,6 @@ import (
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/errors"
"github.com/tendermint/basecoin/state"
"github.com/tendermint/basecoin/txs"
)
const (
@ -25,7 +24,7 @@ func TestPermissionSandbox(t *testing.T) {
// generic args
ctx := NewContext("test-chain", log.NewNopLogger())
store := state.NewMemKVStore()
raw := txs.NewRaw([]byte{1, 2, 3, 4})
raw := NewRawTx([]byte{1, 2, 3, 4})
rawBytes, err := data.ToWire(raw)
require.Nil(err)

View File

@ -159,9 +159,9 @@ checkSendTx() {
if [ -n "$DEBUG" ]; then echo $TX; echo; fi
assertEquals "proper height" $2 $(echo $TX | jq .height)
assertEquals "type=sig" '"sig"' $(echo $TX | jq .data.type)
assertEquals "type=sigs/one" '"sigs/one"' $(echo $TX | jq .data.type)
CTX=$(echo $TX | jq .data.data.tx)
assertEquals "type=chain" '"chain"' $(echo $CTX | jq .type)
assertEquals "type=chain/tx" '"chain/tx"' $(echo $CTX | jq .type)
STX=$(echo $CTX | jq .data.tx)
assertEquals "type=coin/send" '"coin/send"' $(echo $STX | jq .type)
assertEquals "proper sender" "\"$3\"" $(echo $STX | jq .data.inputs[0].address.addr)

View File

@ -82,9 +82,9 @@ test03AddCount() {
TX=$(${CLIENT_EXE} query tx $HASH --trace)
if assertTrue "found tx" $?; then
assertEquals "proper height" $TX_HEIGHT $(echo $TX | jq .height)
assertEquals "type=sig" '"sig"' $(echo $TX | jq .data.type)
assertEquals "type=sigs/one" '"sigs/one"' $(echo $TX | jq .data.type)
CTX=$(echo $TX | jq .data.data.tx)
assertEquals "type=chain" '"chain"' $(echo $CTX | jq .type)
assertEquals "type=chain/tx" '"chain/tx"' $(echo $CTX | jq .type)
CNTX=$(echo $CTX | jq .data.tx)
assertEquals "type=cntr/count" '"cntr/count"' $(echo $CNTX | jq .type)
assertEquals "proper fee" "10" $(echo $CNTX | jq .data.fee[0].amount)

View File

@ -1,104 +0,0 @@
package txs
import (
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/errors"
"github.com/tendermint/go-wire/data"
)
const (
// for utils...
ByteRaw = 0x1
ByteMulti = 0x2
ByteChain = 0x3
// for signatures
ByteSig = 0x16
ByteMultiSig = 0x17
)
const (
// for utils...
TypeRaw = "raw"
TypeMulti = "multi"
TypeChain = "chain"
// for signatures
TypeSig = "sig"
TypeMultiSig = "multisig"
)
const (
rawMaxSize = 2000 * 1000
)
func init() {
basecoin.TxMapper.
RegisterImplementation(Raw{}, TypeRaw, ByteRaw).
RegisterImplementation(&MultiTx{}, TypeMulti, ByteMulti).
RegisterImplementation(&Chain{}, TypeChain, ByteChain)
}
// Raw just contains bytes that can be hex-ified
type Raw struct {
data.Bytes
}
func (r Raw) Wrap() basecoin.Tx {
return basecoin.Tx{r}
}
func (r Raw) ValidateBasic() error {
if len(r.Bytes) > rawMaxSize {
return errors.ErrTooLarge()
}
return nil
}
func NewRaw(d []byte) basecoin.Tx {
return Raw{data.Bytes(d)}.Wrap()
}
/**** MultiTx ******/
type MultiTx struct {
Txs []basecoin.Tx `json:"txs"`
}
func NewMultiTx(txs ...basecoin.Tx) basecoin.Tx {
return (&MultiTx{Txs: txs}).Wrap()
}
func (mt *MultiTx) Wrap() basecoin.Tx {
return basecoin.Tx{mt}
}
func (mt *MultiTx) ValidateBasic() error {
for _, t := range mt.Txs {
err := t.ValidateBasic()
if err != nil {
return err
}
}
return nil
}
/*** Chain ****/
// Chain locks this tx to one chain, wrap with this before signing
type Chain struct {
Tx basecoin.Tx `json:"tx"`
ChainID string `json:"chain_id"`
}
func NewChain(chainID string, tx basecoin.Tx) basecoin.Tx {
return (&Chain{Tx: tx, ChainID: chainID}).Wrap()
}
func (c *Chain) Wrap() basecoin.Tx {
return basecoin.Tx{c}
}
func (c *Chain) ValidateBasic() error {
// TODO: more checks? chainID?
return c.Tx.ValidateBasic()
}