You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
3.4 KiB

  1. package main
  2. import (
  3. "crypto/rand"
  4. "encoding/binary"
  5. "encoding/hex"
  6. "flag"
  7. "fmt"
  8. "os"
  9. "strconv"
  10. "strings"
  11. "sync"
  12. "time"
  13. "github.com/tendermint/go-rpc/client"
  14. rpctypes "github.com/tendermint/go-rpc/types"
  15. )
  16. func main() {
  17. flag.Parse()
  18. args := flag.Args()
  19. if len(args) < 2 {
  20. fmt.Println("transact.go expects at least two arguments (ntxs, hosts)")
  21. os.Exit(1)
  22. }
  23. nTxS, hostS := args[0], args[1]
  24. nTxs, err := strconv.Atoi(nTxS)
  25. if err != nil {
  26. fmt.Println("ntxs must be an integer:", err)
  27. os.Exit(1)
  28. }
  29. hosts := strings.Split(hostS, ",")
  30. errCh := make(chan error, 1000)
  31. wg := new(sync.WaitGroup)
  32. wg.Add(len(hosts))
  33. start := time.Now()
  34. fmt.Printf("Sending %d txs on every host %v\n", nTxs, hosts)
  35. for i, host := range hosts {
  36. go broadcastTxsToHost(wg, errCh, i, host, nTxs, 0)
  37. }
  38. wg.Wait()
  39. fmt.Println("Done broadcasting txs. Took", time.Since(start))
  40. }
  41. func broadcastTxsToHost(wg *sync.WaitGroup, errCh chan error, valI int, valHost string, nTxs int, txCount int) {
  42. reconnectSleepSeconds := time.Second * 1
  43. // thisStart := time.Now()
  44. // cli := rpcclient.NewClientURI(valHost + ":26657")
  45. fmt.Println("Connecting to host to broadcast txs", valI, valHost)
  46. cli := rpcclient.NewWSClient(valHost, "/websocket")
  47. if _, err := cli.Start(); err != nil {
  48. if nTxs == 0 {
  49. time.Sleep(reconnectSleepSeconds)
  50. broadcastTxsToHost(wg, errCh, valI, valHost, nTxs, txCount)
  51. return
  52. }
  53. fmt.Printf("Error starting websocket connection to val%d (%s): %v\n", valI, valHost, err)
  54. os.Exit(1)
  55. }
  56. reconnect := make(chan struct{})
  57. go func(count int) {
  58. LOOP:
  59. for {
  60. ticker := time.NewTicker(reconnectSleepSeconds)
  61. select {
  62. case <-cli.ResultsCh:
  63. count += 1
  64. // nTxs == 0 means just loop forever
  65. if nTxs > 0 && count == nTxs {
  66. break LOOP
  67. }
  68. case err := <-cli.ErrorsCh:
  69. fmt.Println("err: val", valI, valHost, err)
  70. case <-cli.Quit:
  71. broadcastTxsToHost(wg, errCh, valI, valHost, nTxs, count)
  72. return
  73. case <-reconnect:
  74. broadcastTxsToHost(wg, errCh, valI, valHost, nTxs, count)
  75. return
  76. case <-ticker.C:
  77. if nTxs == 0 {
  78. cli.Stop()
  79. broadcastTxsToHost(wg, errCh, valI, valHost, nTxs, count)
  80. return
  81. }
  82. }
  83. }
  84. fmt.Printf("Received all responses from node %d (%s)\n", valI, valHost)
  85. wg.Done()
  86. }(txCount)
  87. var i = 0
  88. for {
  89. /* if i%(nTxs/4) == 0 {
  90. fmt.Printf("Have sent %d txs to node %d. Total time so far: %v\n", i, valI, time.Since(thisStart))
  91. }*/
  92. if !cli.IsRunning() {
  93. return
  94. }
  95. tx := generateTx(i, valI)
  96. if err := cli.WriteJSON(rpctypes.RPCRequest{
  97. JSONRPC: "2.0",
  98. ID: "",
  99. Method: "broadcast_tx_async",
  100. Params: []interface{}{hex.EncodeToString(tx)},
  101. }); err != nil {
  102. fmt.Printf("Error sending tx %d to validator %d: %v. Attempt reconnect\n", i, valI, err)
  103. reconnect <- struct{}{}
  104. return
  105. }
  106. i += 1
  107. if nTxs > 0 && i >= nTxs {
  108. break
  109. } else if nTxs == 0 {
  110. time.Sleep(time.Millisecond * 1)
  111. }
  112. }
  113. fmt.Printf("Done sending %d txs to node s%d (%s)\n", nTxs, valI, valHost)
  114. }
  115. func generateTx(i, valI int) []byte {
  116. // a tx encodes the validator index, the tx number, and some random junk
  117. // TODO: read random bytes into more of the tx
  118. tx := make([]byte, 250)
  119. binary.PutUvarint(tx[:32], uint64(valI))
  120. binary.PutUvarint(tx[32:64], uint64(i))
  121. if _, err := rand.Read(tx[234:]); err != nil {
  122. fmt.Println("err reading from crypto/rand", err)
  123. os.Exit(1)
  124. }
  125. return tx
  126. }