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.

98 lines
2.8 KiB

9 years ago
  1. package core
  2. import (
  3. "fmt"
  4. "time"
  5. ctypes "github.com/tendermint/tendermint/rpc/core/types"
  6. "github.com/tendermint/tendermint/types"
  7. tmsp "github.com/tendermint/tmsp/types"
  8. )
  9. //-----------------------------------------------------------------------------
  10. // NOTE: tx should be signed, but this is only checked at the app level (not by Tendermint!)
  11. // Returns right away, with no response
  12. func BroadcastTxAsync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
  13. err := mempool.CheckTx(tx, nil)
  14. if err != nil {
  15. return nil, fmt.Errorf("Error broadcasting transaction: %v", err)
  16. }
  17. return &ctypes.ResultBroadcastTx{}, nil
  18. }
  19. // Returns with the response from CheckTx
  20. func BroadcastTxSync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
  21. resCh := make(chan *tmsp.Response, 1)
  22. err := mempool.CheckTx(tx, func(res *tmsp.Response) {
  23. resCh <- res
  24. })
  25. if err != nil {
  26. return nil, fmt.Errorf("Error broadcasting transaction: %v", err)
  27. }
  28. res := <-resCh
  29. r := res.GetCheckTx()
  30. return &ctypes.ResultBroadcastTx{
  31. Code: r.Code,
  32. Data: r.Data,
  33. Log: r.Log,
  34. }, nil
  35. }
  36. // CONTRACT: only returns error if mempool.BroadcastTx errs (ie. problem with the app)
  37. // or if we timeout waiting for tx to commit
  38. func BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) {
  39. // subscribe to tx being committed in block
  40. appendTxResCh := make(chan types.EventDataTx, 1)
  41. types.AddListenerForEvent(eventSwitch, "rpc", types.EventStringTx(tx), func(data types.TMEventData) {
  42. appendTxResCh <- data.(types.EventDataTx)
  43. })
  44. // broadcast the tx and register checktx callback
  45. checkTxResCh := make(chan *tmsp.Response, 1)
  46. err := mempool.CheckTx(tx, func(res *tmsp.Response) {
  47. checkTxResCh <- res
  48. })
  49. if err != nil {
  50. return nil, fmt.Errorf("Error broadcasting transaction: %v", err)
  51. }
  52. checkTxRes := <-checkTxResCh
  53. checkTxR := checkTxRes.GetCheckTx()
  54. if checkTxR.Code != tmsp.CodeType_OK {
  55. // CheckTx failed!
  56. return &ctypes.ResultBroadcastTxCommit{
  57. CheckTx: checkTxR,
  58. AppendTx: nil,
  59. }, nil
  60. }
  61. // Wait for the tx to be included in a block,
  62. // timeout after something reasonable.
  63. timer := time.NewTimer(60 * 5 * time.Second)
  64. select {
  65. case appendTxRes := <-appendTxResCh:
  66. // The tx was included in a block.
  67. appendTxR := appendTxRes.GetAppendTx()
  68. return &ctypes.ResultBroadcastTxCommit{
  69. CheckTx: checkTxR,
  70. AppendTx: appendTxR,
  71. }, nil
  72. case <-timer.C:
  73. return &ctypes.ResultBroadcastTxCommit{
  74. CheckTx: checkTxR,
  75. AppendTx: nil,
  76. }, fmt.Errorf("Timed out waiting for transaction to be included in a block")
  77. }
  78. panic("Should never happen!")
  79. }
  80. func UnconfirmedTxs() (*ctypes.ResultUnconfirmedTxs, error) {
  81. txs := mempool.Reap(-1)
  82. return &ctypes.ResultUnconfirmedTxs{len(txs), txs}, nil
  83. }
  84. func NumUnconfirmedTxs() (*ctypes.ResultUnconfirmedTxs, error) {
  85. return &ctypes.ResultUnconfirmedTxs{N: mempool.Size()}, nil
  86. }