websocket server sends pings; added ws_client; events refactor
This commit is contained in:
parent
37c68e838e
commit
60310cc23f
3
Makefile
3
Makefile
|
@ -10,6 +10,7 @@ install:
|
|||
go install github.com/tendermint/tendermint/cmd/debora
|
||||
go install github.com/tendermint/tendermint/cmd/stdinwriter
|
||||
go install github.com/tendermint/tendermint/cmd/logjack
|
||||
go install github.com/tendermint/tendermint/cmd/sim_txs
|
||||
@echo `git rev-parse --verify HEAD` >> $(TMROOT)/revisions
|
||||
|
||||
build:
|
||||
|
@ -18,6 +19,7 @@ build:
|
|||
go build -o build/debora github.com/tendermint/tendermint/cmd/debora
|
||||
go build -o build/stdinwriter github.com/tendermint/tendermint/cmd/stdinwriter
|
||||
go build -o build/logjack github.com/tendermint/tendermint/cmd/logjack
|
||||
go build -o build/sim_txs github.com/tendermint/tendermint/cmd/sim_txs
|
||||
|
||||
build_race:
|
||||
go build -race -o build/tendermint github.com/tendermint/tendermint/cmd/tendermint
|
||||
|
@ -25,6 +27,7 @@ build_race:
|
|||
go build -race -o build/debora github.com/tendermint/tendermint/cmd/debora
|
||||
go build -race -o build/stdinwriter github.com/tendermint/tendermint/cmd/stdinwriter
|
||||
go build -race -o build/logjack github.com/tendermint/tendermint/cmd/logjack
|
||||
go build -race -o build/sim_txs github.com/tendermint/tendermint/cmd/sim_txs
|
||||
|
||||
test: build
|
||||
-rm -rf ~/.tendermint_test_bak
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
acm "github.com/tendermint/tendermint/account"
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
|
@ -18,26 +16,26 @@ const Version = "0.0.1"
|
|||
const sleepSeconds = 1 // Every second
|
||||
|
||||
// Parse command-line options
|
||||
func parseFlags() (privKeyHex string, numAccounts int, remote string, version bool) {
|
||||
func parseFlags() (privKeyHex string, numAccounts int, remote string) {
|
||||
var version bool
|
||||
flag.StringVar(&privKeyHex, "priv-key", "", "Private key bytes in HEX")
|
||||
flag.IntVar(&numAccounts, "num-accounts", 1000, "Deterministically generates this many sub-accounts")
|
||||
flag.StringVar(&remote, "remote", "http://localhost:46657", "Remote RPC host:port")
|
||||
flag.BoolVar(&version, "version", false, "Version")
|
||||
flag.Parse()
|
||||
if version {
|
||||
Exit(Fmt("sim_txs version %v", Version))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
// Read options
|
||||
privKeyHex, numAccounts, remote, version := parseFlags()
|
||||
if version {
|
||||
fmt.Println(Fmt("sim_txs version %v", Version))
|
||||
return
|
||||
}
|
||||
privKeyHex, numAccounts, remote := parseFlags()
|
||||
|
||||
// Print args.
|
||||
// fmt.Println(privKeyHex, numAccounts, remote, version)
|
||||
// fmt.Println(privKeyHex, numAccounts, remote)
|
||||
|
||||
privKeyBytes, err := hex.DecodeString(privKeyHex)
|
||||
if err != nil {
|
||||
|
@ -57,33 +55,55 @@ func main() {
|
|||
fmt.Println("Root account", rootAccount)
|
||||
}
|
||||
|
||||
go func() {
|
||||
// Construct a new send Tx
|
||||
accounts := make([]*acm.Account, numAccounts)
|
||||
privAccounts := make([]*acm.PrivAccount, numAccounts)
|
||||
for i := 0; i < numAccounts; i++ {
|
||||
privAccounts[i] = root.Generate(i)
|
||||
account, err := getAccount(remote, privAccounts[i].Address)
|
||||
if err != nil {
|
||||
fmt.Println("Error", err)
|
||||
return
|
||||
} else {
|
||||
accounts[i] = account
|
||||
}
|
||||
// Load all accounts
|
||||
accounts := make([]*acm.Account, numAccounts+1)
|
||||
accounts[0] = rootAccount
|
||||
privAccounts := make([]*acm.PrivAccount, numAccounts+1)
|
||||
privAccounts[0] = root
|
||||
for i := 1; i < numAccounts; i++ {
|
||||
privAccounts[i] = root.Generate(i)
|
||||
account, err := getAccount(remote, privAccounts[i].Address)
|
||||
if err != nil {
|
||||
fmt.Println("Error", err)
|
||||
return
|
||||
} else {
|
||||
accounts[i] = account
|
||||
}
|
||||
}
|
||||
|
||||
// Test: send from root to accounts[1]
|
||||
sendTx := makeRandomTransaction(10, rootAccount.Sequence+1, root, 2, accounts)
|
||||
fmt.Println(sendTx)
|
||||
|
||||
wsClient, err := rpcclient.NewWSClient("http://localhost:46657/websocket")
|
||||
if err != nil {
|
||||
Exit(Fmt("Failed to establish websocket connection: %v", err))
|
||||
}
|
||||
wsClient.Subscribe(types.EventStringAccInput(sendTx.Outputs[0].Address))
|
||||
|
||||
go func() {
|
||||
for {
|
||||
sendTx := makeRandomTransaction(rootAccount, root, accounts, privAccounts)
|
||||
// Broadcast it.
|
||||
err := broadcastSendTx(remote, sendTx)
|
||||
if err != nil {
|
||||
Exit(Fmt("Failed to broadcast SendTx: %v", err))
|
||||
return
|
||||
}
|
||||
// Broadcast 1 tx!
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
foo := <-wsClient.EventsCh
|
||||
fmt.Println("!!", foo)
|
||||
}
|
||||
}()
|
||||
|
||||
/*
|
||||
go func() {
|
||||
for {
|
||||
sendTx := makeRandomTransaction(rootAccount, root, accounts, privAccounts)
|
||||
// Broadcast it.
|
||||
err := broadcastSendTx(remote, sendTx)
|
||||
if err != nil {
|
||||
Exit(Fmt("Failed to broadcast SendTx: %v", err))
|
||||
return
|
||||
}
|
||||
// Broadcast 1 tx!
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
}()
|
||||
*/
|
||||
|
||||
// Trap signal
|
||||
TrapSignal(func() {
|
||||
fmt.Println("sim_txs shutting down")
|
||||
|
@ -112,64 +132,43 @@ func broadcastSendTx(remote string, sendTx *types.SendTx) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func makeRandomTransaction(rootAccount *acm.Account, rootPrivAccount *acm.PrivAccount, accounts []*acm.Account, privAccounts []*acm.PrivAccount) *types.SendTx {
|
||||
allAccounts := append(accounts, rootAccount)
|
||||
allPrivAccounts := append(privAccounts, rootPrivAccount)
|
||||
// Make a random send transaction from srcIndex to N other accounts.
|
||||
// balance: balance to send from input
|
||||
// sequence: sequence to sign with
|
||||
// inputPriv: input privAccount
|
||||
func makeRandomTransaction(balance int64, sequence int, inputPriv *acm.PrivAccount, sendCount int, accounts []*acm.Account) *types.SendTx {
|
||||
|
||||
// Find accout with the most money
|
||||
inputBalance := int64(0)
|
||||
inputAccount := (*acm.Account)(nil)
|
||||
inputPrivAccount := (*acm.PrivAccount)(nil)
|
||||
for i, account := range allAccounts {
|
||||
if account == nil {
|
||||
continue
|
||||
}
|
||||
if inputBalance < account.Balance {
|
||||
inputBalance = account.Balance
|
||||
inputAccount = account
|
||||
inputPrivAccount = allPrivAccounts[i]
|
||||
}
|
||||
}
|
||||
if inputAccount == nil {
|
||||
Exit("No accounts have any money")
|
||||
return nil
|
||||
}
|
||||
// Remember which accounts were chosen
|
||||
accMap := map[string]struct{}{}
|
||||
accMap[string(inputPriv.Address)] = struct{}{}
|
||||
|
||||
// Find a selection of accounts to send to
|
||||
outputAccounts := map[string]*acm.Account{}
|
||||
for i := 0; i < 2; i++ {
|
||||
outputs := []*acm.Account{}
|
||||
for i := 0; i < sendCount; i++ {
|
||||
for {
|
||||
idx := RandInt() % len(accounts)
|
||||
if bytes.Equal(accounts[idx].Address, inputAccount.Address) {
|
||||
account := accounts[idx]
|
||||
if _, ok := accMap[string(account.Address)]; ok {
|
||||
continue
|
||||
}
|
||||
if _, ok := outputAccounts[string(accounts[idx].Address)]; ok {
|
||||
continue
|
||||
}
|
||||
outputAccounts[string(accounts[idx].Address)] = accounts[idx]
|
||||
accMap[string(account.Address)] = struct{}{}
|
||||
outputs = append(outputs, account)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Construct SendTx
|
||||
sendTx := types.NewSendTx()
|
||||
err := sendTx.AddInputWithNonce(inputPrivAccount.PubKey, inputAccount.Balance, inputAccount.Sequence+1)
|
||||
err := sendTx.AddInputWithNonce(inputPriv.PubKey, balance, sequence)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, outputAccount := range outputAccounts {
|
||||
sendTx.AddOutput(outputAccount.Address, inputAccount.Balance/int64(len(outputAccounts)))
|
||||
// XXX FIXME???
|
||||
outputAccount.Balance += inputAccount.Balance / int64(len(outputAccounts))
|
||||
for _, output := range outputs {
|
||||
sendTx.AddOutput(output.Address, balance/int64(len(outputs)))
|
||||
}
|
||||
|
||||
// Sign SendTx
|
||||
sendTx.SignInput("tendermint_testnet_7", 0, inputPrivAccount)
|
||||
|
||||
// Hack: Listen for events or create a new RPC call for this.
|
||||
// XXX FIXME
|
||||
inputAccount.Sequence += 1
|
||||
inputAccount.Balance = 0 // FIXME???
|
||||
sendTx.SignInput("tendermint_testnet_9", 0, inputPriv)
|
||||
|
||||
return sendTx
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ import (
|
|||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/tendermint/tendermint/wire"
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
. "github.com/tendermint/tendermint/rpc/types"
|
||||
"github.com/tendermint/tendermint/wire"
|
||||
)
|
||||
|
||||
func Call(remote string, method string, params []interface{}, dest interface{}) (interface{}, error) {
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
package rpcclient
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/gorilla/websocket"
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
_ "github.com/tendermint/tendermint/config/tendermint_test"
|
||||
"github.com/tendermint/tendermint/rpc/types"
|
||||
"github.com/tendermint/tendermint/wire"
|
||||
)
|
||||
|
||||
const wsEventsChannelCapacity = 10
|
||||
const wsResponsesChannelCapacity = 10
|
||||
|
||||
type WSClient struct {
|
||||
QuitService
|
||||
*websocket.Conn
|
||||
EventsCh chan rpctypes.RPCEventResult
|
||||
ResponsesCh chan rpctypes.RPCResponse
|
||||
}
|
||||
|
||||
// create a new connection
|
||||
func NewWSClient(addr string) (*WSClient, error) {
|
||||
dialer := websocket.DefaultDialer
|
||||
rHeader := http.Header{}
|
||||
con, _, err := dialer.Dial(addr, rHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wsClient := &WSClient{
|
||||
Conn: con,
|
||||
EventsCh: make(chan rpctypes.RPCEventResult, wsEventsChannelCapacity),
|
||||
ResponsesCh: make(chan rpctypes.RPCResponse, wsResponsesChannelCapacity),
|
||||
}
|
||||
wsClient.QuitService = *NewQuitService(log, "WSClient", wsClient)
|
||||
return wsClient, nil
|
||||
}
|
||||
|
||||
func (wsc *WSClient) OnStart() {
|
||||
wsc.QuitService.OnStart()
|
||||
go wsc.receiveEventsRoutine()
|
||||
}
|
||||
|
||||
func (wsc *WSClient) OnStop() {
|
||||
wsc.QuitService.OnStop()
|
||||
}
|
||||
|
||||
func (wsc *WSClient) receiveEventsRoutine() {
|
||||
for {
|
||||
_, data, err := wsc.ReadMessage()
|
||||
if err != nil {
|
||||
log.Info("WSClient failed to read message: %v", err)
|
||||
wsc.Stop()
|
||||
break
|
||||
} else {
|
||||
var response rpctypes.RPCResponse
|
||||
if err := json.Unmarshal(data, &response); err != nil {
|
||||
log.Info("WSClient failed to parse message: %v", err)
|
||||
wsc.Stop()
|
||||
break
|
||||
}
|
||||
if strings.HasSuffix(response.Id, "#event") {
|
||||
var eventResult rpctypes.RPCEventResult
|
||||
var err error
|
||||
wire.ReadJSONObject(&eventResult, response.Result, &err)
|
||||
if err != nil {
|
||||
log.Info("WSClient failed to parse RPCEventResult: %v", err)
|
||||
wsc.Stop()
|
||||
break
|
||||
}
|
||||
wsc.EventsCh <- eventResult
|
||||
} else {
|
||||
wsc.ResponsesCh <- response
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// subscribe to an event
|
||||
func (wsc *WSClient) Subscribe(eventid string) error {
|
||||
err := wsc.WriteJSON(rpctypes.RPCRequest{
|
||||
JSONRPC: "2.0",
|
||||
Id: "",
|
||||
Method: "subscribe",
|
||||
Params: []interface{}{eventid},
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// unsubscribe from an event
|
||||
func (wsc *WSClient) Unsubscribe(eventid string) error {
|
||||
err := wsc.WriteJSON(rpctypes.RPCRequest{
|
||||
JSONRPC: "2.0",
|
||||
Id: "",
|
||||
Method: "unsubscribe",
|
||||
Params: []interface{}{eventid},
|
||||
})
|
||||
return err
|
||||
}
|
|
@ -12,10 +12,10 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/gorilla/websocket"
|
||||
"github.com/tendermint/tendermint/wire"
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
"github.com/tendermint/tendermint/events"
|
||||
. "github.com/tendermint/tendermint/rpc/types"
|
||||
"github.com/tendermint/tendermint/wire"
|
||||
)
|
||||
|
||||
func RegisterRPCFuncs(mux *http.ServeMux, funcMap map[string]*RPCFunc) {
|
||||
|
@ -205,8 +205,9 @@ func _jsonStringToArg(ty reflect.Type, arg string) (reflect.Value, error) {
|
|||
|
||||
const (
|
||||
writeChanCapacity = 20
|
||||
WSWriteTimeoutSeconds = 10 // exposed for tests
|
||||
WSReadTimeoutSeconds = 10 // exposed for tests
|
||||
wsWriteTimeoutSeconds = 30 // each write times out after this
|
||||
wsReadTimeoutSeconds = 30 // connection times out if we haven't received *anything* in this long, not even pings.
|
||||
wsPingTickerSeconds = 10 // send a ping every PingTickerSeconds.
|
||||
)
|
||||
|
||||
// a single websocket connection
|
||||
|
@ -219,6 +220,7 @@ type WSConnection struct {
|
|||
baseConn *websocket.Conn
|
||||
writeChan chan RPCResponse
|
||||
readTimeout *time.Timer
|
||||
pingTicker *time.Timer
|
||||
|
||||
funcMap map[string]*RPCFunc
|
||||
evsw *events.EventSwitch
|
||||
|
@ -245,14 +247,15 @@ func (wsc *WSConnection) OnStart() {
|
|||
go wsc.readRoutine()
|
||||
|
||||
// Custom Ping handler to touch readTimeout
|
||||
wsc.readTimeout = time.NewTimer(time.Second * WSReadTimeoutSeconds)
|
||||
wsc.readTimeout = time.NewTimer(time.Second * wsReadTimeoutSeconds)
|
||||
wsc.pingTicker = time.NewTimer(time.Second * wsPingTickerSeconds)
|
||||
wsc.baseConn.SetPingHandler(func(m string) error {
|
||||
wsc.baseConn.WriteControl(websocket.PongMessage, []byte(m), time.Now().Add(time.Second*WSWriteTimeoutSeconds))
|
||||
wsc.readTimeout.Reset(time.Second * WSReadTimeoutSeconds)
|
||||
wsc.baseConn.WriteControl(websocket.PongMessage, []byte(m), time.Now().Add(time.Second*wsWriteTimeoutSeconds))
|
||||
wsc.readTimeout.Reset(time.Second * wsReadTimeoutSeconds)
|
||||
return nil
|
||||
})
|
||||
wsc.baseConn.SetPongHandler(func(m string) error {
|
||||
wsc.readTimeout.Reset(time.Second * WSReadTimeoutSeconds)
|
||||
wsc.readTimeout.Reset(time.Second * wsReadTimeoutSeconds)
|
||||
return nil
|
||||
})
|
||||
go wsc.readTimeoutRoutine()
|
||||
|
@ -265,6 +268,7 @@ func (wsc *WSConnection) OnStop() {
|
|||
wsc.QuitService.OnStop()
|
||||
wsc.evsw.RemoveListener(wsc.id)
|
||||
wsc.readTimeout.Stop()
|
||||
wsc.pingTicker.Stop()
|
||||
// The write loop closes the websocket connection
|
||||
// when it exits its loop, and the read loop
|
||||
// closes the writeChan
|
||||
|
@ -302,7 +306,7 @@ func (wsc *WSConnection) readRoutine() {
|
|||
default:
|
||||
var in []byte
|
||||
// Do not set a deadline here like below:
|
||||
// wsc.baseConn.SetReadDeadline(time.Now().Add(time.Second * WSReadTimeoutSeconds))
|
||||
// wsc.baseConn.SetReadDeadline(time.Now().Add(time.Second * wsReadTimeoutSeconds))
|
||||
// The client may not send anything for a while.
|
||||
// We use `readTimeout` to handle read timeouts.
|
||||
_, in, err := wsc.baseConn.ReadMessage()
|
||||
|
@ -332,7 +336,8 @@ func (wsc *WSConnection) readRoutine() {
|
|||
} else {
|
||||
log.Notice("Subscribe to event", "id", wsc.id, "event", event)
|
||||
wsc.evsw.AddListenerForEvent(wsc.id, event, func(msg interface{}) {
|
||||
wsc.writeRPCResponse(NewRPCResponse(request.Id, RPCEventResult{event, msg}, ""))
|
||||
// NOTE: RPCResponses of subscribed events have id suffix "#event"
|
||||
wsc.writeRPCResponse(NewRPCResponse(request.Id+"#event", RPCEventResult{event, msg}, ""))
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
@ -340,6 +345,7 @@ func (wsc *WSConnection) readRoutine() {
|
|||
if len(request.Params) == 0 {
|
||||
log.Notice("Unsubscribe from all events", "id", wsc.id)
|
||||
wsc.evsw.RemoveListener(wsc.id)
|
||||
wsc.writeRPCResponse(NewRPCResponse(request.Id, nil, ""))
|
||||
continue
|
||||
} else if len(request.Params) == 1 {
|
||||
if event, ok := request.Params[0].(string); !ok {
|
||||
|
@ -348,6 +354,7 @@ func (wsc *WSConnection) readRoutine() {
|
|||
} else {
|
||||
log.Notice("Unsubscribe from event", "id", wsc.id, "event", event)
|
||||
wsc.evsw.RemoveListenerForEvent(event, wsc.id)
|
||||
wsc.writeRPCResponse(NewRPCResponse(request.Id, nil, ""))
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
|
@ -383,19 +390,26 @@ func (wsc *WSConnection) readRoutine() {
|
|||
// receives on a write channel and writes out on the socket
|
||||
func (wsc *WSConnection) writeRoutine() {
|
||||
defer wsc.baseConn.Close()
|
||||
n, err := new(int64), new(error)
|
||||
var n, err = int64(0), error(nil)
|
||||
for {
|
||||
select {
|
||||
case <-wsc.Quit:
|
||||
return
|
||||
case <-wsc.pingTicker.C:
|
||||
err := wsc.baseConn.WriteMessage(websocket.PingMessage, []byte{})
|
||||
if err != nil {
|
||||
log.Error("Failed to write ping message on websocket", "error", err)
|
||||
wsc.Stop()
|
||||
return
|
||||
}
|
||||
case msg := <-wsc.writeChan:
|
||||
buf := new(bytes.Buffer)
|
||||
wire.WriteJSON(msg, buf, n, err)
|
||||
if *err != nil {
|
||||
wire.WriteJSON(msg, buf, &n, &err)
|
||||
if err != nil {
|
||||
log.Error("Failed to marshal RPCResponse to JSON", "error", err)
|
||||
} else {
|
||||
wsc.baseConn.SetWriteDeadline(time.Now().Add(time.Second * WSWriteTimeoutSeconds))
|
||||
if err := wsc.baseConn.WriteMessage(websocket.TextMessage, buf.Bytes()); err != nil {
|
||||
wsc.baseConn.SetWriteDeadline(time.Now().Add(time.Second * wsWriteTimeoutSeconds))
|
||||
if err = wsc.baseConn.WriteMessage(websocket.TextMessage, buf.Bytes()); err != nil {
|
||||
log.Warn("Failed to write response on websocket", "error", err)
|
||||
wsc.Stop()
|
||||
return
|
||||
|
@ -407,8 +421,9 @@ func (wsc *WSConnection) writeRoutine() {
|
|||
|
||||
//----------------------------------------
|
||||
|
||||
// main manager for all websocket connections
|
||||
// holds the event switch
|
||||
// Main manager for all websocket connections
|
||||
// Holds the event switch
|
||||
// NOTE: The websocket path is defined externally, e.g. in node/node.go
|
||||
type WebsocketManager struct {
|
||||
websocket.Upgrader
|
||||
funcMap map[string]*RPCFunc
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
|
||||
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/gorilla/websocket"
|
||||
_ "github.com/tendermint/tendermint/config/tendermint_test"
|
||||
"github.com/tendermint/tendermint/rpc/server"
|
||||
"github.com/tendermint/tendermint/rpc/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
"github.com/tendermint/tendermint/wire"
|
||||
|
@ -66,20 +65,22 @@ func waitForEvent(t *testing.T, con *websocket.Conn, eventid string, dieOnTimeou
|
|||
quitCh := make(chan struct{})
|
||||
defer close(quitCh)
|
||||
|
||||
// Write pings repeatedly
|
||||
// TODO: Maybe move this out to something that manages the con?
|
||||
go func() {
|
||||
pingTicker := time.NewTicker((time.Second * rpcserver.WSReadTimeoutSeconds) / 2)
|
||||
for {
|
||||
select {
|
||||
case <-quitCh:
|
||||
pingTicker.Stop()
|
||||
return
|
||||
case <-pingTicker.C:
|
||||
con.WriteControl(websocket.PingMessage, []byte("whatevs"), time.Now().Add(time.Second))
|
||||
/*
|
||||
// TODO delete: we moved pinging to the server.
|
||||
// Write pings repeatedly
|
||||
go func() {
|
||||
pingTicker := time.NewTicker((time.Second * rpcserver.WSReadTimeoutSeconds) / 2)
|
||||
for {
|
||||
select {
|
||||
case <-quitCh:
|
||||
pingTicker.Stop()
|
||||
return
|
||||
case <-pingTicker.C:
|
||||
con.WriteControl(websocket.PingMessage, []byte("whatevs"), time.Now().Add(time.Second))
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}()
|
||||
*/
|
||||
|
||||
// Read message
|
||||
go func() {
|
||||
|
@ -212,8 +213,8 @@ func unmarshalValidateSend(amt int64, toAddr []byte) func(string, []byte) error
|
|||
JSONRPC string `json:"jsonrpc"`
|
||||
Id string `json:"id"`
|
||||
Result struct {
|
||||
Event string `json:"event"`
|
||||
Data *types.SendTx `json:"data"`
|
||||
Event string `json:"event"`
|
||||
Data types.EventMsgTx `json:"data"`
|
||||
} `json:"result"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
@ -228,7 +229,7 @@ func unmarshalValidateSend(amt int64, toAddr []byte) func(string, []byte) error
|
|||
if eid != response.Result.Event {
|
||||
return fmt.Errorf("Eventid is not correct. Got %s, expected %s", response.Result.Event, eid)
|
||||
}
|
||||
tx := response.Result.Data
|
||||
tx := response.Result.Data.Tx.(*types.SendTx)
|
||||
if bytes.Compare(tx.Inputs[0].Address, user[0].Address) != 0 {
|
||||
return fmt.Errorf("Senders do not match up! Got %x, expected %x", tx.Inputs[0].Address, user[0].Address)
|
||||
}
|
||||
|
|
|
@ -337,11 +337,11 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab
|
|||
// if the evc is nil, nothing will happen
|
||||
if evc != nil {
|
||||
for _, i := range tx.Inputs {
|
||||
evc.FireEvent(types.EventStringAccInput(i.Address), tx)
|
||||
evc.FireEvent(types.EventStringAccInput(i.Address), types.EventMsgTx{tx, nil, ""})
|
||||
}
|
||||
|
||||
for _, o := range tx.Outputs {
|
||||
evc.FireEvent(types.EventStringAccOutput(o.Address), tx)
|
||||
evc.FireEvent(types.EventStringAccOutput(o.Address), types.EventMsgTx{tx, nil, ""})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -494,8 +494,8 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab
|
|||
if err != nil {
|
||||
exception = err.Error()
|
||||
}
|
||||
evc.FireEvent(types.EventStringAccInput(tx.Input.Address), types.EventMsgCallTx{tx, ret, exception})
|
||||
evc.FireEvent(types.EventStringAccOutput(tx.Address), types.EventMsgCallTx{tx, ret, exception})
|
||||
evc.FireEvent(types.EventStringAccInput(tx.Input.Address), types.EventMsgTx{tx, ret, exception})
|
||||
evc.FireEvent(types.EventStringAccOutput(tx.Address), types.EventMsgTx{tx, ret, exception})
|
||||
}
|
||||
} else {
|
||||
// The mempool does not call txs until
|
||||
|
@ -893,7 +893,7 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab
|
|||
}
|
||||
|
||||
if evc != nil {
|
||||
evc.FireEvent(types.EventStringAccInput(tx.Input.Address), tx)
|
||||
evc.FireEvent(types.EventStringAccInput(tx.Input.Address), types.EventMsgTx{tx, nil, ""})
|
||||
evc.FireEvent(types.EventStringPermissions(ptypes.PermFlagToString(permFlag)), tx)
|
||||
}
|
||||
|
||||
|
|
|
@ -1073,7 +1073,7 @@ func execTxWaitEvent(t *testing.T, blockCache *BlockCache, tx types.Tx, eventid
|
|||
}
|
||||
|
||||
switch ev := msg.(type) {
|
||||
case types.EventMsgCallTx:
|
||||
case types.EventMsgTx:
|
||||
return ev, ev.Exception
|
||||
case types.EventMsgCall:
|
||||
return ev, ev.Exception
|
||||
|
|
|
@ -6,58 +6,22 @@ import (
|
|||
|
||||
// Functions to generate eventId strings
|
||||
|
||||
func EventStringAccInput(addr []byte) string {
|
||||
return fmt.Sprintf("Acc/%X/Input", addr)
|
||||
}
|
||||
|
||||
func EventStringAccOutput(addr []byte) string {
|
||||
return fmt.Sprintf("Acc/%X/Output", addr)
|
||||
}
|
||||
|
||||
func EventStringAccCall(addr []byte) string {
|
||||
return fmt.Sprintf("Acc/%X/Call", addr)
|
||||
}
|
||||
|
||||
func EventStringLogEvent(addr []byte) string {
|
||||
return fmt.Sprintf("Log/%X", addr)
|
||||
}
|
||||
|
||||
func EventStringPermissions(name string) string {
|
||||
return fmt.Sprintf("Permissions/%s", name)
|
||||
}
|
||||
|
||||
func EventStringNameReg(name string) string {
|
||||
return fmt.Sprintf("NameReg/%s", name)
|
||||
}
|
||||
|
||||
func EventStringBond() string {
|
||||
return "Bond"
|
||||
}
|
||||
|
||||
func EventStringUnbond() string {
|
||||
return "Unbond"
|
||||
}
|
||||
|
||||
func EventStringRebond() string {
|
||||
return "Rebond"
|
||||
}
|
||||
|
||||
func EventStringDupeout() string {
|
||||
return "Dupeout"
|
||||
}
|
||||
|
||||
func EventStringNewBlock() string {
|
||||
return "NewBlock"
|
||||
}
|
||||
|
||||
func EventStringFork() string {
|
||||
return "Fork"
|
||||
}
|
||||
func EventStringAccInput(addr []byte) string { return fmt.Sprintf("Acc/%X/Input", addr) }
|
||||
func EventStringAccOutput(addr []byte) string { return fmt.Sprintf("Acc/%X/Output", addr) }
|
||||
func EventStringAccCall(addr []byte) string { return fmt.Sprintf("Acc/%X/Call", addr) }
|
||||
func EventStringLogEvent(addr []byte) string { return fmt.Sprintf("Log/%X", addr) }
|
||||
func EventStringPermissions(name string) string { return fmt.Sprintf("Permissions/%s", name) }
|
||||
func EventStringBond() string { return "Bond" }
|
||||
func EventStringUnbond() string { return "Unbond" }
|
||||
func EventStringRebond() string { return "Rebond" }
|
||||
func EventStringDupeout() string { return "Dupeout" }
|
||||
func EventStringNewBlock() string { return "NewBlock" }
|
||||
func EventStringFork() string { return "Fork" }
|
||||
|
||||
// Most event messages are basic types (a block, a transaction)
|
||||
// but some (an input to a call tx or a receive) are more exotic:
|
||||
|
||||
type EventMsgCallTx struct {
|
||||
type EventMsgTx struct {
|
||||
Tx Tx `json:"tx"`
|
||||
Return []byte `json:"return"`
|
||||
Exception string `json:"exception"`
|
||||
|
|
|
@ -175,7 +175,7 @@ func runVMWaitEvents(t *testing.T, ourVm *VM, caller, callee *Account, subscribe
|
|||
}()
|
||||
msg := <-ch
|
||||
switch ev := msg.(type) {
|
||||
case types.EventMsgCallTx:
|
||||
case types.EventMsgTx:
|
||||
return ev.Exception
|
||||
case types.EventMsgCall:
|
||||
return ev.Exception
|
||||
|
|
Loading…
Reference in New Issue