From 6029f5c986a26f8c3dbbee908024ac7b8d8a00b6 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 18 May 2017 17:11:26 +0200 Subject: [PATCH] Introduce the concept of TxLayer --- tx.go | 18 ++++++++++++++++++ tx_test.go | 35 +++++++++++++++++++++++++++++++++++ txs/base.go | 43 ++++++++++++++++++++++++++++++++----------- txs/sigs_test.go | 12 ++++++------ 4 files changed, 91 insertions(+), 17 deletions(-) create mode 100644 tx_test.go diff --git a/tx.go b/tx.go index 3ee3dc5fe..5a74a7f90 100644 --- a/tx.go +++ b/tx.go @@ -3,4 +3,22 @@ package basecoin // TODO: add some common functionality here... // +gen wrapper:"Tx" type TxInner interface { + Wrap() Tx +} + +// TxLayer provides a standard way to deal with "middleware" tx, +// That add context to an embedded tx. +type TxLayer interface { + TxInner + Next() Tx +} + +func (t Tx) IsLayer() bool { + _, ok := t.Unwrap().(TxLayer) + return ok +} + +func (t Tx) GetLayer() TxLayer { + l, _ := t.Unwrap().(TxLayer) + return l } diff --git a/tx_test.go b/tx_test.go new file mode 100644 index 000000000..1d4894063 --- /dev/null +++ b/tx_test.go @@ -0,0 +1,35 @@ +package basecoin + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +// define a Demo struct that implements TxLayer +type Demo struct{} + +var _ TxLayer = Demo{} + +func (d Demo) Next() Tx { return Tx{} } +func (d Demo) Wrap() Tx { return Tx{d} } + +// define a Fake struct that doesn't implement TxLayer +type Fake struct{} + +func (f Fake) Wrap() Tx { return Tx{f} } + +// Make sure the layer +func TestLayer(t *testing.T) { + assert := assert.New(t) + + // a fake tx, just don't use it... + nl := Fake{}.Wrap() + assert.False(nl.IsLayer()) + assert.Nil(nl.GetLayer()) + + // a tx containing a TxLayer should respond properly + l := Demo{}.Wrap() + assert.True(l.IsLayer()) + assert.NotNil(l.GetLayer()) +} diff --git a/txs/base.go b/txs/base.go index 04ab877c3..384aafc29 100644 --- a/txs/base.go +++ b/txs/base.go @@ -30,29 +30,50 @@ const ( func init() { basecoin.TxMapper. - RegisterImplementation(data.Bytes{}, TypeRaw, ByteRaw). + RegisterImplementation(Raw{}, TypeRaw, ByteRaw). RegisterImplementation(&Fee{}, TypeFees, ByteFees) } -// WrapBytes converts data.Bytes into a Tx, so we -// can just pass raw bytes and display in hex in json -func WrapBytes(d []byte) basecoin.Tx { - return basecoin.Tx{data.Bytes(d)} +// Raw just contains bytes that can be hex-ified +type Raw struct { + data.Bytes } -/**** One Sig ****/ +func (r Raw) Wrap() basecoin.Tx { + return basecoin.Tx{r} +} -// OneSig lets us wrap arbitrary data with a go-crypto signature +func NewRaw(d []byte) Raw { + return Raw{data.Bytes(d)} +} + +/**** Fee ****/ + +// Fee attaches a fee payment to the embedded tx type Fee struct { - Tx basecoin.Tx `json:"tx"` - Fee types.Coin `json:"fee"` + Tx basecoin.Tx `json:"tx"` + Fee types.Coin `json:"fee"` + Payer data.Bytes `json:"payer"` // the address who pays the fee // Gas types.Coin `json:"gas"` // ????? } -func NewFee(tx basecoin.Tx, fee types.Coin) *Fee { - return &Fee{Tx: tx, Fee: fee} +func NewFee(tx basecoin.Tx, fee types.Coin, addr []byte) *Fee { + return &Fee{Tx: tx, Fee: fee, Payer: addr} } func (f *Fee) Wrap() basecoin.Tx { return basecoin.Tx{f} } + +/**** MultiTx ******/ +type MultiTx struct { + Txs []basecoin.Tx `json:"txs"` +} + +func NewMultiTx(txs ...basecoin.Tx) *MultiTx { + return &MultiTx{Txs: txs} +} + +func (mt *MultiTx) Wrap() basecoin.Tx { + return basecoin.Tx{mt} +} diff --git a/txs/sigs_test.go b/txs/sigs_test.go index f0a5a2c99..1e51bff09 100644 --- a/txs/sigs_test.go +++ b/txs/sigs_test.go @@ -6,13 +6,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tendermint/basecoin" 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/go-wire/data" + + "github.com/tendermint/basecoin" ) func checkSignBytes(t *testing.T, bytes []byte, expected string) { @@ -22,9 +22,9 @@ 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 - byt, ok := preTx.Unwrap().(data.Bytes) + raw, ok := preTx.Unwrap().(Raw) require.True(t, ok) - assert.Equal(t, expected, string(byt)) + assert.Equal(t, expected, string(raw.Bytes)) } func TestOneSig(t *testing.T) { @@ -54,7 +54,7 @@ func TestOneSig(t *testing.T) { } for _, tc := range cases { - inner := WrapBytes([]byte(tc.data)) + inner := NewRaw([]byte(tc.data)).Wrap() tx := NewSig(inner) // unsigned version _, err = tx.Signers() @@ -119,7 +119,7 @@ func TestMultiSig(t *testing.T) { } for _, tc := range cases { - inner := WrapBytes([]byte(tc.data)) + inner := NewRaw([]byte(tc.data)).Wrap() tx := NewMulti(inner) // unsigned version _, err = tx.Signers()