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.

251 lines
7.6 KiB

  1. package types
  2. import (
  3. // for registering TMEventData as events.EventData
  4. abci "github.com/tendermint/abci/types"
  5. "github.com/tendermint/go-wire/data"
  6. cmn "github.com/tendermint/tmlibs/common"
  7. "github.com/tendermint/tmlibs/events"
  8. )
  9. // Functions to generate eventId strings
  10. // Reserved
  11. func EventStringBond() string { return "Bond" }
  12. func EventStringUnbond() string { return "Unbond" }
  13. func EventStringRebond() string { return "Rebond" }
  14. func EventStringDupeout() string { return "Dupeout" }
  15. func EventStringFork() string { return "Fork" }
  16. func EventStringTx(tx Tx) string { return cmn.Fmt("Tx:%X", tx.Hash()) }
  17. func EventStringNewBlock() string { return "NewBlock" }
  18. func EventStringNewBlockHeader() string { return "NewBlockHeader" }
  19. func EventStringNewRound() string { return "NewRound" }
  20. func EventStringNewRoundStep() string { return "NewRoundStep" }
  21. func EventStringTimeoutPropose() string { return "TimeoutPropose" }
  22. func EventStringCompleteProposal() string { return "CompleteProposal" }
  23. func EventStringPolka() string { return "Polka" }
  24. func EventStringUnlock() string { return "Unlock" }
  25. func EventStringLock() string { return "Lock" }
  26. func EventStringRelock() string { return "Relock" }
  27. func EventStringTimeoutWait() string { return "TimeoutWait" }
  28. func EventStringVote() string { return "Vote" }
  29. func EventStringProposalHeartbeat() string { return "ProposalHeartbeat" }
  30. //----------------------------------------
  31. var (
  32. EventDataNameNewBlock = "new_block"
  33. EventDataNameNewBlockHeader = "new_block_header"
  34. EventDataNameTx = "tx"
  35. EventDataNameRoundState = "round_state"
  36. EventDataNameVote = "vote"
  37. EventDataNameProposalHeartbeat = "proposer_heartbeat"
  38. )
  39. //----------------------------------------
  40. // implements events.EventData
  41. type TMEventDataInner interface {
  42. events.EventData
  43. }
  44. type TMEventData struct {
  45. TMEventDataInner `json:"unwrap"`
  46. }
  47. func (tmr TMEventData) MarshalJSON() ([]byte, error) {
  48. return tmEventDataMapper.ToJSON(tmr.TMEventDataInner)
  49. }
  50. func (tmr *TMEventData) UnmarshalJSON(data []byte) (err error) {
  51. parsed, err := tmEventDataMapper.FromJSON(data)
  52. if err == nil && parsed != nil {
  53. tmr.TMEventDataInner = parsed.(TMEventDataInner)
  54. }
  55. return
  56. }
  57. func (tmr TMEventData) Unwrap() TMEventDataInner {
  58. tmrI := tmr.TMEventDataInner
  59. for wrap, ok := tmrI.(TMEventData); ok; wrap, ok = tmrI.(TMEventData) {
  60. tmrI = wrap.TMEventDataInner
  61. }
  62. return tmrI
  63. }
  64. func (tmr TMEventData) Empty() bool {
  65. return tmr.TMEventDataInner == nil
  66. }
  67. const (
  68. EventDataTypeNewBlock = byte(0x01)
  69. EventDataTypeFork = byte(0x02)
  70. EventDataTypeTx = byte(0x03)
  71. EventDataTypeNewBlockHeader = byte(0x04)
  72. EventDataTypeRoundState = byte(0x11)
  73. EventDataTypeVote = byte(0x12)
  74. EventDataTypeProposalHeartbeat = byte(0x20)
  75. )
  76. var tmEventDataMapper = data.NewMapper(TMEventData{}).
  77. RegisterImplementation(EventDataNewBlock{}, EventDataNameNewBlock, EventDataTypeNewBlock).
  78. RegisterImplementation(EventDataNewBlockHeader{}, EventDataNameNewBlockHeader, EventDataTypeNewBlockHeader).
  79. RegisterImplementation(EventDataTx{}, EventDataNameTx, EventDataTypeTx).
  80. RegisterImplementation(EventDataRoundState{}, EventDataNameRoundState, EventDataTypeRoundState).
  81. RegisterImplementation(EventDataVote{}, EventDataNameVote, EventDataTypeVote).
  82. RegisterImplementation(EventDataProposalHeartbeat{}, EventDataNameProposalHeartbeat, EventDataTypeProposalHeartbeat)
  83. // Most event messages are basic types (a block, a transaction)
  84. // but some (an input to a call tx or a receive) are more exotic
  85. type EventDataNewBlock struct {
  86. Block *Block `json:"block"`
  87. }
  88. // light weight event for benchmarking
  89. type EventDataNewBlockHeader struct {
  90. Header *Header `json:"header"`
  91. }
  92. // All txs fire EventDataTx
  93. type EventDataTx struct {
  94. Height int `json:"height"`
  95. Tx Tx `json:"tx"`
  96. Data data.Bytes `json:"data"`
  97. Log string `json:"log"`
  98. Code abci.CodeType `json:"code"`
  99. Error string `json:"error"` // this is redundant information for now
  100. }
  101. type EventDataProposalHeartbeat struct {
  102. Heartbeat *Heartbeat
  103. }
  104. // NOTE: This goes into the replay WAL
  105. type EventDataRoundState struct {
  106. Height int `json:"height"`
  107. Round int `json:"round"`
  108. Step string `json:"step"`
  109. // private, not exposed to websockets
  110. RoundState interface{} `json:"-"`
  111. }
  112. type EventDataVote struct {
  113. Vote *Vote
  114. }
  115. func (_ EventDataNewBlock) AssertIsTMEventData() {}
  116. func (_ EventDataNewBlockHeader) AssertIsTMEventData() {}
  117. func (_ EventDataTx) AssertIsTMEventData() {}
  118. func (_ EventDataRoundState) AssertIsTMEventData() {}
  119. func (_ EventDataVote) AssertIsTMEventData() {}
  120. func (_ EventDataProposalHeartbeat) AssertIsTMEventData() {}
  121. //----------------------------------------
  122. // Wrappers for type safety
  123. type Fireable interface {
  124. events.Fireable
  125. }
  126. type Eventable interface {
  127. SetEventSwitch(EventSwitch)
  128. }
  129. type EventSwitch interface {
  130. events.EventSwitch
  131. }
  132. type EventCache interface {
  133. Fireable
  134. Flush()
  135. }
  136. func NewEventSwitch() EventSwitch {
  137. return events.NewEventSwitch()
  138. }
  139. func NewEventCache(evsw EventSwitch) EventCache {
  140. return events.NewEventCache(evsw)
  141. }
  142. // All events should be based on this FireEvent to ensure they are TMEventData
  143. func fireEvent(fireable events.Fireable, event string, data TMEventData) {
  144. if fireable != nil {
  145. fireable.FireEvent(event, data)
  146. }
  147. }
  148. func AddListenerForEvent(evsw EventSwitch, id, event string, cb func(data TMEventData)) {
  149. evsw.AddListenerForEvent(id, event, func(data events.EventData) {
  150. cb(data.(TMEventData))
  151. })
  152. }
  153. //--- block, tx, and vote events
  154. func FireEventNewBlock(fireable events.Fireable, block EventDataNewBlock) {
  155. fireEvent(fireable, EventStringNewBlock(), TMEventData{block})
  156. }
  157. func FireEventNewBlockHeader(fireable events.Fireable, header EventDataNewBlockHeader) {
  158. fireEvent(fireable, EventStringNewBlockHeader(), TMEventData{header})
  159. }
  160. func FireEventVote(fireable events.Fireable, vote EventDataVote) {
  161. fireEvent(fireable, EventStringVote(), TMEventData{vote})
  162. }
  163. func FireEventTx(fireable events.Fireable, tx EventDataTx) {
  164. fireEvent(fireable, EventStringTx(tx.Tx), TMEventData{tx})
  165. }
  166. //--- EventDataRoundState events
  167. func FireEventNewRoundStep(fireable events.Fireable, rs EventDataRoundState) {
  168. fireEvent(fireable, EventStringNewRoundStep(), TMEventData{rs})
  169. }
  170. func FireEventTimeoutPropose(fireable events.Fireable, rs EventDataRoundState) {
  171. fireEvent(fireable, EventStringTimeoutPropose(), TMEventData{rs})
  172. }
  173. func FireEventTimeoutWait(fireable events.Fireable, rs EventDataRoundState) {
  174. fireEvent(fireable, EventStringTimeoutWait(), TMEventData{rs})
  175. }
  176. func FireEventNewRound(fireable events.Fireable, rs EventDataRoundState) {
  177. fireEvent(fireable, EventStringNewRound(), TMEventData{rs})
  178. }
  179. func FireEventCompleteProposal(fireable events.Fireable, rs EventDataRoundState) {
  180. fireEvent(fireable, EventStringCompleteProposal(), TMEventData{rs})
  181. }
  182. func FireEventPolka(fireable events.Fireable, rs EventDataRoundState) {
  183. fireEvent(fireable, EventStringPolka(), TMEventData{rs})
  184. }
  185. func FireEventUnlock(fireable events.Fireable, rs EventDataRoundState) {
  186. fireEvent(fireable, EventStringUnlock(), TMEventData{rs})
  187. }
  188. func FireEventRelock(fireable events.Fireable, rs EventDataRoundState) {
  189. fireEvent(fireable, EventStringRelock(), TMEventData{rs})
  190. }
  191. func FireEventLock(fireable events.Fireable, rs EventDataRoundState) {
  192. fireEvent(fireable, EventStringLock(), TMEventData{rs})
  193. }
  194. func FireEventProposalHeartbeat(fireable events.Fireable, rs EventDataProposalHeartbeat) {
  195. fireEvent(fireable, EventStringProposalHeartbeat(), TMEventData{rs})
  196. }