diff --git a/manager/eris-mint/state/execution.go b/manager/eris-mint/state/execution.go index 54799c38b06213baeb36dad89750fb11f83d1769..34d8afd049e7ae8b3d0879aca10f445965807d52 100644 --- a/manager/eris-mint/state/execution.go +++ b/manager/eris-mint/state/execution.go @@ -279,6 +279,7 @@ func adjustByInputs(accounts map[string]*acm.Account, ins []*txs.TxInput) { PanicSanity("adjustByInputs() expects sufficient funds") } acc.Balance -= in.Amount + acc.Sequence += 1 } } @@ -413,6 +414,7 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable // Good! value := tx.Input.Amount - tx.Fee + inAcc.Sequence += 1 inAcc.Balance -= tx.Fee blockCache.UpdateAccount(inAcc) diff --git a/rpc/tendermint/core/routes.go b/rpc/tendermint/core/routes.go index c00d3f5579cb4d11a87935c65daafe3cb208c20c..02ffadfbf3a2bc07d1d5ce6ee5d565d2b677cd95 100644 --- a/rpc/tendermint/core/routes.go +++ b/rpc/tendermint/core/routes.go @@ -55,6 +55,12 @@ func (tmRoutes *TendermintRoutes) GetRoutes() map[string]*rpc.RPCFunc { func (tmRoutes *TendermintRoutes) Subscribe(wsCtx rpctypes.WSRPCContext, event string) (ctypes.ErisDBResult, error) { // NOTE: RPCResponses of subscribed events have id suffix "#event" + // TODO: we really ought to allow multiple subscriptions from the same client address + // to the same event. The code as it stands reflects the somewhat broken tendermint + // implementation. We can use GenerateSubId to randomize the subscriptions id + // and return it in the result. This would require clients to hang on to a + // subscription id if they wish to unsubscribe, but then again they can just + // drop their connection result, err := tmRoutes.tendermintPipe.Subscribe(wsCtx.GetRemoteAddr(), event, func(result ctypes.ErisDBResult) { // NOTE: EventSwitch callbacks must be nonblocking diff --git a/rpc/tendermint/test/client_ws_test.go b/rpc/tendermint/test/client_ws_test.go index d1fe45f9cab59b95857807ecfb525a3d4edff5b0..69153da425e711d7ef9ab9ab67b1af01b9db777c 100644 --- a/rpc/tendermint/test/client_ws_test.go +++ b/rpc/tendermint/test/client_ws_test.go @@ -29,8 +29,8 @@ func TestWSNewBlock(t *testing.T) { wsc.Stop() }() waitForEvent(t, wsc, eid, true, func() {}, - func(eid string, b interface{}) error { - fmt.Println("Check:", string(b.([]byte))) + func(eid string, eventData txs.EventData) error { + fmt.Println("Check: ", eventData.(txs.EventDataNewBlock).Block) return nil }) } @@ -48,7 +48,26 @@ func TestWSBlockchainGrowth(t *testing.T) { wsc.Stop() }() // listen for NewBlock, ensure height increases by 1 - unmarshalValidateBlockchain(t, wsc, eid) + var initBlockN int + for i := 0; i < 2; i++ { + waitForEvent(t, wsc, eid, true, func() {}, + func(eid string, eventData txs.EventData) error { + eventDataNewBlock, ok := eventData.(txs.EventDataNewBlock) + if !ok { + t.Fatalf("Was expecting EventDataNewBlock but got %v", eventData) + } + block := eventDataNewBlock.Block + if i == 0 { + initBlockN = block.Height + } else { + if block.Header.Height != initBlockN+i { + return fmt.Errorf("Expected block %d, got block %d", i, block.Header.Height) + } + } + + return nil + }) + } } // send a transaction and validate the events from listening for both sender and receiver @@ -91,12 +110,12 @@ func TestWSDoubleFire(t *testing.T) { waitForEvent(t, wsc, eid, true, func() { tx := makeDefaultSendTxSigned(t, wsTyp, toAddr, amt) broadcastTx(t, wsTyp, tx) - }, func(eid string, b interface{}) error { + }, func(eid string, b txs.EventData) error { return nil }) // but make sure we don't hear about it twice waitForEvent(t, wsc, eid, false, func() { - }, func(eid string, b interface{}) error { + }, func(eid string, b txs.EventData) error { return nil }) } @@ -201,7 +220,7 @@ func TestWSCallCall(t *testing.T) { // let the contract get created first waitForEvent(t, wsc, eid1, true, func() { - }, func(eid string, b interface{}) error { + }, func(eid string, b txs.EventData) error { return nil }) // call it diff --git a/rpc/tendermint/test/tests.go b/rpc/tendermint/test/tests.go index 3f2646ea1f169ec622a22140963d35ef795c51ff..832534e9b0ec12f97f26470fa85f7900fadf5f78 100644 --- a/rpc/tendermint/test/tests.go +++ b/rpc/tendermint/test/tests.go @@ -12,7 +12,9 @@ import ( "golang.org/x/crypto/ripemd160" ) -var doNothing = func(eid string, b interface{}) error { return nil } +func doNothing(eventId string, eventData txs.EventData) error { + return nil +} func testStatus(t *testing.T, typ string) { client := clients[typ] @@ -30,7 +32,7 @@ func testStatus(t *testing.T, typ string) { func testGetAccount(t *testing.T, typ string) { acc := getAccount(t, typ, user[0].Address) if acc == nil { - t.Fatalf("Account was nil") + t.Fatal("Account was nil") } if bytes.Compare(acc.Address, user[0].Address) != 0 { t.Fatalf("Failed to get correct account. Got %x, expected %x", acc.Address, user[0].Address) @@ -192,9 +194,7 @@ func testNameReg(t *testing.T, typ string) { tx := makeDefaultNameTx(t, typ, name, data, amt, fee) broadcastTx(t, typ, tx) // verify the name by both using the event and by checking get_name - waitForEvent(t, wsc, eid, true, func() {}, func(eid string, b interface{}) error { - // TODO: unmarshal the response - _ = b // TODO + waitForEvent(t, wsc, eid, true, func() {}, func(eid string, b txs.EventData) error { // TODO: unmarshal thtxs.EventData _ = b // TODO tx, err := unmarshalResponseNameReg([]byte{}) if err != nil { return err diff --git a/rpc/tendermint/test/ws_helpers.go b/rpc/tendermint/test/ws_helpers.go index cb631fd0d9f1dda7cc76db8a4d67a323759e1b0d..76c624109634c60669930b0d450829131e5bbfff 100644 --- a/rpc/tendermint/test/ws_helpers.go +++ b/rpc/tendermint/test/ws_helpers.go @@ -8,7 +8,7 @@ import ( "time" ctypes "github.com/eris-ltd/eris-db/rpc/tendermint/core/types" - txtypes "github.com/eris-ltd/eris-db/txs" + "github.com/eris-ltd/eris-db/txs" "github.com/tendermint/tendermint/types" "github.com/tendermint/go-events" @@ -18,7 +18,7 @@ import ( ) const ( - timeoutSeconds = 5 + timeoutSeconds = 2 ) //-------------------------------------------------------------------------------- @@ -50,9 +50,9 @@ func unsubscribe(t *testing.T, wsc *client.WSClient, eventid string) { // wait for an event; do things that might trigger events, and check them when they are received // the check function takes an event id and the byte slice read off the ws func waitForEvent(t *testing.T, wsc *client.WSClient, eventid string, - dieOnTimeout bool, f func(), check func(string, interface{}) error) { + dieOnTimeout bool, f func(), check func(string, txs.EventData) error) { // go routine to wait for webscoket msg - goodCh := make(chan interface{}) + goodCh := make(chan txs.EventData) errCh := make(chan error) // Read message @@ -132,7 +132,7 @@ func unmarshalResponseNewBlock(b []byte) (*types.Block, error) { return nil, nil } -func unmarshalResponseNameReg(b []byte) (*txtypes.NameTx, error) { +func unmarshalResponseNameReg(b []byte) (*txs.NameTx, error) { // unmarshall and assert somethings var response rpctypes.RPCResponse var err error @@ -144,48 +144,17 @@ func unmarshalResponseNameReg(b []byte) (*txtypes.NameTx, error) { return nil, fmt.Errorf(response.Error) } _, val := UnmarshalEvent(*response.Result) - tx := txtypes.DecodeTx(val.(types.EventDataTx).Tx).(*txtypes.NameTx) + tx := txs.DecodeTx(val.(types.EventDataTx).Tx).(*txs.NameTx) return tx, nil } -func unmarshalValidateBlockchain(t *testing.T, wsc *client.WSClient, eid string) { - var initBlockN int - for i := 0; i < 2; i++ { - waitForEvent(t, wsc, eid, true, func() {}, func(eid string, b interface{}) error { - block, err := unmarshalResponseNewBlock(b.([]byte)) - if err != nil { - return err - } - if i == 0 { - initBlockN = block.Header.Height - } else { - if block.Header.Height != initBlockN+i { - return fmt.Errorf("Expected block %d, got block %d", i, block.Header.Height) - } - } - - return nil - }) - } -} - -func unmarshalValidateSend(amt int64, toAddr []byte) func(string, interface{}) error { - return func(eid string, b interface{}) error { - // unmarshal and assert correctness - var response rpctypes.RPCResponse - var err error - wire.ReadJSON(&response, b.([]byte), &err) - if err != nil { - return err - } - if response.Error != "" { - return fmt.Errorf(response.Error) - } - event, val := UnmarshalEvent(*response.Result) - if eid != event { - return fmt.Errorf("Eventid is not correct. Got %s, expected %s", event, eid) +func unmarshalValidateSend(amt int64, toAddr []byte) func(string, txs.EventData) error { + return func(eid string, eventData txs.EventData) error { + var data = eventData.(txs.EventDataTx) + if data.Exception != "" { + return fmt.Errorf(data.Exception) } - tx := txtypes.DecodeTx(val.(types.EventDataTx).Tx).(*txtypes.SendTx) + tx := data.Tx.(*txs.SendTx) if !bytes.Equal(tx.Inputs[0].Address, user[0].Address) { return fmt.Errorf("Senders do not match up! Got %x, expected %x", tx.Inputs[0].Address, user[0].Address) } @@ -199,24 +168,13 @@ func unmarshalValidateSend(amt int64, toAddr []byte) func(string, interface{}) e } } -func unmarshalValidateTx(amt int64, returnCode []byte) func(string, interface{}) error { - return func(eid string, b interface{}) error { - // unmarshall and assert somethings - var response rpctypes.RPCResponse - var err error - wire.ReadJSON(&response, b.([]byte), &err) - if err != nil { - return err - } - if response.Error != "" { - return fmt.Errorf(response.Error) - } - _, val := UnmarshalEvent(*response.Result) - var data = val.(txtypes.EventDataTx) +func unmarshalValidateTx(amt int64, returnCode []byte) func(string, txs.EventData) error { + return func(eid string, eventData txs.EventData) error { + var data = eventData.(txs.EventDataTx) if data.Exception != "" { return fmt.Errorf(data.Exception) } - tx := data.Tx.(*txtypes.CallTx) + tx := data.Tx.(*txs.CallTx) if !bytes.Equal(tx.Input.Address, user[0].Address) { return fmt.Errorf("Senders do not match up! Got %x, expected %x", tx.Input.Address, user[0].Address) @@ -233,20 +191,9 @@ func unmarshalValidateTx(amt int64, returnCode []byte) func(string, interface{}) } } -func unmarshalValidateCall(origin, returnCode []byte, txid *[]byte) func(string, interface{}) error { - return func(eid string, b interface{}) error { - // unmarshall and assert somethings - var response rpctypes.RPCResponse - var err error - wire.ReadJSON(&response, b.([]byte), &err) - if err != nil { - return err - } - if response.Error != "" { - return fmt.Errorf(response.Error) - } - _, val := UnmarshalEvent(*response.Result) - var data = val.(txtypes.EventDataCall) +func unmarshalValidateCall(origin, returnCode []byte, txid *[]byte) func(string, txs.EventData) error { + return func(eid string, eventData txs.EventData) error { + var data = eventData.(txs.EventDataCall) if data.Exception != "" { return fmt.Errorf(data.Exception) }