Moved content of txs package to sit next to the handlers
This commit is contained in:
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
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
|
||||
or multiple private key signatures using straightforward algorithms.
|
||||
It currently does not support N-of-M key share signing of other more
|
||||
complex algorithms (although it would be great to add them).
|
||||
|
||||
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 auth
|
||||
|
||||
import (
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
"github.com/tendermint/go-crypto/keys"
|
||||
"github.com/tendermint/go-wire/data"
|
||||
|
||||
"github.com/tendermint/basecoin"
|
||||
"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()
|
||||
}
|
||||
|
||||
/**** Registration ****/
|
||||
|
||||
func init() {
|
||||
basecoin.TxMapper.
|
||||
RegisterImplementation(&OneSig{}, TypeSingleTx, ByteSingleTx).
|
||||
RegisterImplementation(&MultiSig{}, TypeMultiSig, ByteMultiSig)
|
||||
}
|
||||
|
||||
/**** One Sig ****/
|
||||
|
||||
// OneSig lets us wrap arbitrary data with a go-crypto signature
|
||||
type OneSig struct {
|
||||
Tx basecoin.Tx `json:"tx"`
|
||||
Signed `json:"signature"`
|
||||
}
|
||||
|
||||
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}
|
||||
}
|
||||
|
||||
func (s *OneSig) Wrap() basecoin.Tx {
|
||||
return basecoin.Tx{s}
|
||||
}
|
||||
|
||||
func (s *OneSig) Next() basecoin.Tx {
|
||||
return s.Tx
|
||||
}
|
||||
|
||||
func (s *OneSig) ValidateBasic() error {
|
||||
return s.Tx.ValidateBasic()
|
||||
}
|
||||
|
||||
// TxBytes returns the full data with signatures
|
||||
func (s *OneSig) TxBytes() ([]byte, error) {
|
||||
return data.ToWire(s.Wrap())
|
||||
}
|
||||
|
||||
// SignBytes returns the original data passed into `NewSig`
|
||||
func (s *OneSig) SignBytes() []byte {
|
||||
res, err := data.ToWire(s.Tx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Sign will add a signature and pubkey.
|
||||
//
|
||||
// Depending on the Signable, one may be able to call this multiple times for multisig
|
||||
// Returns error if called with invalid data or too many times
|
||||
func (s *OneSig) Sign(pubkey crypto.PubKey, sig crypto.Signature) error {
|
||||
signed := Signed{sig, pubkey}
|
||||
if signed.Empty() {
|
||||
return errors.ErrMissingSignature()
|
||||
}
|
||||
if !s.Empty() {
|
||||
return errors.ErrTooManySignatures()
|
||||
}
|
||||
// set the value once we are happy
|
||||
s.Signed = signed
|
||||
return nil
|
||||
}
|
||||
|
||||
// Signers will return the public key(s) that signed if the signature
|
||||
// is valid, or an error if there is any issue with the signature,
|
||||
// including if there are no signatures
|
||||
func (s *OneSig) Signers() ([]crypto.PubKey, error) {
|
||||
if s.Empty() {
|
||||
return nil, errors.ErrMissingSignature()
|
||||
}
|
||||
if !s.Pubkey.VerifyBytes(s.SignBytes(), s.Sig) {
|
||||
return nil, errors.ErrInvalidSignature()
|
||||
}
|
||||
return []crypto.PubKey{s.Pubkey}, nil
|
||||
}
|
||||
|
||||
/**** MultiSig ****/
|
||||
|
||||
// MultiSig lets us wrap arbitrary data with a go-crypto signature
|
||||
type MultiSig struct {
|
||||
Tx basecoin.Tx `json:"tx"`
|
||||
Sigs []Signed `json:"signatures"`
|
||||
}
|
||||
|
||||
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}
|
||||
}
|
||||
|
||||
func (s *MultiSig) Wrap() basecoin.Tx {
|
||||
return basecoin.Tx{s}
|
||||
}
|
||||
|
||||
func (s *MultiSig) Next() basecoin.Tx {
|
||||
return s.Tx
|
||||
}
|
||||
|
||||
func (s *MultiSig) ValidateBasic() error {
|
||||
return s.Tx.ValidateBasic()
|
||||
}
|
||||
|
||||
// TxBytes returns the full data with signatures
|
||||
func (s *MultiSig) TxBytes() ([]byte, error) {
|
||||
return data.ToWire(s.Wrap())
|
||||
}
|
||||
|
||||
// SignBytes returns the original data passed into `NewSig`
|
||||
func (s *MultiSig) SignBytes() []byte {
|
||||
res, err := data.ToWire(s.Tx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Sign will add a signature and pubkey.
|
||||
//
|
||||
// Depending on the Signable, one may be able to call this multiple times for multisig
|
||||
// Returns error if called with invalid data or too many times
|
||||
func (s *MultiSig) Sign(pubkey crypto.PubKey, sig crypto.Signature) error {
|
||||
signed := Signed{sig, pubkey}
|
||||
if signed.Empty() {
|
||||
return errors.ErrMissingSignature()
|
||||
}
|
||||
// set the value once we are happy
|
||||
s.Sigs = append(s.Sigs, signed)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Signers will return the public key(s) that signed if the signature
|
||||
// is valid, or an error if there is any issue with the signature,
|
||||
// including if there are no signatures
|
||||
func (s *MultiSig) Signers() ([]crypto.PubKey, error) {
|
||||
if len(s.Sigs) == 0 {
|
||||
return nil, errors.ErrMissingSignature()
|
||||
}
|
||||
// verify all the signatures before returning them
|
||||
keys := make([]crypto.PubKey, len(s.Sigs))
|
||||
data := s.SignBytes()
|
||||
for i := range s.Sigs {
|
||||
ms := s.Sigs[i]
|
||||
if !ms.Pubkey.VerifyBytes(data, ms.Sig) {
|
||||
return nil, errors.ErrInvalidSignature()
|
||||
}
|
||||
keys[i] = ms.Pubkey
|
||||
}
|
||||
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
func Sign(tx keys.Signable, key crypto.PrivKey) error {
|
||||
msg := tx.SignBytes()
|
||||
pubkey := key.PubKey()
|
||||
sig := key.Sign(msg)
|
||||
return tx.Sign(pubkey, sig)
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"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"
|
||||
"github.com/tendermint/go-crypto/keys/storage/memstorage"
|
||||
wire "github.com/tendermint/go-wire"
|
||||
|
||||
"github.com/tendermint/basecoin"
|
||||
)
|
||||
|
||||
func checkSignBytes(t *testing.T, bytes []byte, expected string) {
|
||||
// load it back... unwrap the tx
|
||||
var preTx basecoin.Tx
|
||||
err := wire.ReadBinaryBytes(bytes, &preTx)
|
||||
require.Nil(t, err)
|
||||
|
||||
// now make sure this tx is data.Bytes with the info we want
|
||||
raw, ok := preTx.Unwrap().(stack.RawTx)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, expected, string(raw.Bytes))
|
||||
}
|
||||
|
||||
func TestOneSig(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
algo := crypto.NameEd25519
|
||||
cstore := cryptostore.New(
|
||||
cryptostore.SecretBox,
|
||||
memstorage.New(),
|
||||
keys.MustLoadCodec("english"),
|
||||
)
|
||||
n, p := "foo", "bar"
|
||||
n2, p2 := "other", "thing"
|
||||
|
||||
acct, _, err := cstore.Create(n, p, algo)
|
||||
require.Nil(err, "%+v", err)
|
||||
acct2, _, err := cstore.Create(n2, p2, algo)
|
||||
require.Nil(err, "%+v", err)
|
||||
|
||||
cases := []struct {
|
||||
data string
|
||||
key keys.Info
|
||||
name, pass string
|
||||
}{
|
||||
{"first", acct, n, p},
|
||||
{"kehfkhefy8y", acct, n, p},
|
||||
{"second", acct2, n2, p2},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
inner := stack.NewRawTx([]byte(tc.data)).Wrap()
|
||||
tx := NewSig(inner)
|
||||
// unsigned version
|
||||
_, err = tx.Signers()
|
||||
assert.NotNil(err)
|
||||
orig, err := tx.TxBytes()
|
||||
require.Nil(err, "%+v", err)
|
||||
data := tx.SignBytes()
|
||||
checkSignBytes(t, data, tc.data)
|
||||
|
||||
// sign it
|
||||
err = cstore.Sign(tc.name, tc.pass, tx)
|
||||
require.Nil(err, "%+v", err)
|
||||
// but not twice
|
||||
err = cstore.Sign(tc.name, tc.pass, tx)
|
||||
require.NotNil(err)
|
||||
|
||||
// make sure it is proper now
|
||||
sigs, err := tx.Signers()
|
||||
require.Nil(err, "%+v", err)
|
||||
if assert.Equal(1, len(sigs)) {
|
||||
// This must be refactored...
|
||||
assert.Equal(tc.key.PubKey, sigs[0])
|
||||
}
|
||||
// the tx bytes should change after this
|
||||
after, err := tx.TxBytes()
|
||||
require.Nil(err, "%+v", err)
|
||||
assert.NotEqual(orig, after, "%X != %X", orig, after)
|
||||
|
||||
// sign bytes are the same
|
||||
data = tx.SignBytes()
|
||||
checkSignBytes(t, data, tc.data)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultiSig(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
algo := crypto.NameEd25519
|
||||
cstore := cryptostore.New(
|
||||
cryptostore.SecretBox,
|
||||
memstorage.New(),
|
||||
keys.MustLoadCodec("english"),
|
||||
)
|
||||
n, p := "foo", "bar"
|
||||
n2, p2 := "other", "thing"
|
||||
|
||||
acct, _, err := cstore.Create(n, p, algo)
|
||||
require.Nil(err, "%+v", err)
|
||||
acct2, _, err := cstore.Create(n2, p2, algo)
|
||||
require.Nil(err, "%+v", err)
|
||||
|
||||
type signer struct {
|
||||
key keys.Info
|
||||
name, pass string
|
||||
}
|
||||
cases := []struct {
|
||||
data string
|
||||
signers []signer
|
||||
}{
|
||||
{"one", []signer{{acct, n, p}}},
|
||||
{"two", []signer{{acct2, n2, p2}}},
|
||||
{"both", []signer{{acct, n, p}, {acct2, n2, p2}}},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
inner := stack.NewRawTx([]byte(tc.data)).Wrap()
|
||||
tx := NewMulti(inner)
|
||||
// unsigned version
|
||||
_, err = tx.Signers()
|
||||
assert.NotNil(err)
|
||||
orig, err := tx.TxBytes()
|
||||
require.Nil(err, "%+v", err)
|
||||
data := tx.SignBytes()
|
||||
checkSignBytes(t, data, tc.data)
|
||||
|
||||
// sign it
|
||||
for _, s := range tc.signers {
|
||||
err = cstore.Sign(s.name, s.pass, tx)
|
||||
require.Nil(err, "%+v", err)
|
||||
}
|
||||
|
||||
// make sure it is proper now
|
||||
sigs, err := tx.Signers()
|
||||
require.Nil(err, "%+v", err)
|
||||
if assert.Equal(len(tc.signers), len(sigs)) {
|
||||
for i := range sigs {
|
||||
// This must be refactored...
|
||||
assert.Equal(tc.signers[i].key.PubKey, sigs[i])
|
||||
}
|
||||
}
|
||||
// the tx bytes should change after this
|
||||
after, err := tx.TxBytes()
|
||||
require.Nil(err, "%+v", err)
|
||||
assert.NotEqual(orig, after, "%X != %X", orig, after)
|
||||
|
||||
// sign bytes are the same
|
||||
data = tx.SignBytes()
|
||||
checkSignBytes(t, data, tc.data)
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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"},
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
func TestEncoding(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
raw := stack.NewRawTx([]byte{0x34, 0xa7})
|
||||
raw2 := stack.NewRawTx([]byte{0x73, 0x86, 0x22})
|
||||
|
||||
cases := []struct {
|
||||
Tx basecoin.Tx
|
||||
}{
|
||||
{raw},
|
||||
{NewMultiTx(raw, raw2)},
|
||||
{NewChainTx("foobar", raw)},
|
||||
}
|
||||
|
||||
for idx, tc := range cases {
|
||||
i := strconv.Itoa(idx)
|
||||
tx := tc.Tx
|
||||
|
||||
// test json in and out
|
||||
js, err := data.ToJSON(tx)
|
||||
require.Nil(err, i)
|
||||
var jtx basecoin.Tx
|
||||
err = data.FromJSON(js, &jtx)
|
||||
require.Nil(err, i)
|
||||
assert.Equal(tx, jtx, i)
|
||||
|
||||
// test wire in and out
|
||||
bin, err := data.ToWire(tx)
|
||||
require.Nil(err, i)
|
||||
var wtx basecoin.Tx
|
||||
err = data.FromWire(bin, &wtx)
|
||||
require.Nil(err, i)
|
||||
assert.Equal(tx, wtx, i)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user