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.

168 lines
4.6 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package types
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "sync"
  6. "github.com/tendermint/go-crypto"
  7. "github.com/tendermint/go-event-meter"
  8. "github.com/tendermint/go-events"
  9. client "github.com/tendermint/go-rpc/client"
  10. "github.com/tendermint/go-wire"
  11. ctypes "github.com/tendermint/tendermint/rpc/core/types"
  12. tmtypes "github.com/tendermint/tendermint/types"
  13. )
  14. //------------------------------------------------
  15. // validator types
  16. //------------------------------------------------
  17. //------------------------------------------------
  18. // simple validator set and validator (just crypto, no network)
  19. // validator set (independent of chains)
  20. type ValidatorSet struct {
  21. ID string `json:"id"`
  22. Validators []*Validator `json:"validators"`
  23. }
  24. func (vs *ValidatorSet) Validator(valID string) (*Validator, error) {
  25. for _, v := range vs.Validators {
  26. if v.ID == valID {
  27. return v, nil
  28. }
  29. }
  30. return nil, fmt.Errorf("Unknwon validator %s", valID)
  31. }
  32. // validator (independent of chain)
  33. type Validator struct {
  34. ID string `json:"id"`
  35. PubKey crypto.PubKey `json:"pub_key"`
  36. Chains []string `json:"chains,omitempty"` // TODO: put this elsewhere (?)
  37. }
  38. //------------------------------------------------
  39. // Live validator on a chain
  40. // Validator on a chain
  41. // Returned over RPC but also used to manage state
  42. // Responsible for communication with the validator
  43. type ValidatorState struct {
  44. Config *ValidatorConfig `json:"config"`
  45. Status *ValidatorStatus `json:"status"`
  46. // Currently we get IPs and dial,
  47. // but should reverse so the nodes dial the netmon,
  48. // both for node privacy and easier reconfig (validators changing ip/port)
  49. em *eventmeter.EventMeter // holds a ws connection to the val
  50. client *client.ClientURI // rpc client
  51. }
  52. // Start a new event meter, including the websocket connection
  53. // Also create the http rpc client for convenienve
  54. func (vs *ValidatorState) Start() error {
  55. // we need the lock because RPCAddr can be updated concurrently
  56. vs.Config.mtx.Lock()
  57. rpcAddr := vs.Config.RPCAddr
  58. vs.Config.mtx.Unlock()
  59. em := eventmeter.NewEventMeter(fmt.Sprintf("ws://%s/websocket", rpcAddr), UnmarshalEvent)
  60. if err := em.Start(); err != nil {
  61. return err
  62. }
  63. vs.em = em
  64. vs.client = client.NewClientURI(fmt.Sprintf("http://%s", rpcAddr))
  65. return nil
  66. }
  67. func (vs *ValidatorState) Stop() {
  68. vs.em.Stop()
  69. }
  70. func (vs *ValidatorState) EventMeter() *eventmeter.EventMeter {
  71. return vs.em
  72. }
  73. func (vs *ValidatorState) NewBlock(block *tmtypes.Block) {
  74. vs.Status.mtx.Lock()
  75. defer vs.Status.mtx.Unlock()
  76. vs.Status.BlockHeight = block.Header.Height
  77. }
  78. func (vs *ValidatorState) UpdateLatency(latency float64) float64 {
  79. vs.Status.mtx.Lock()
  80. defer vs.Status.mtx.Unlock()
  81. old := vs.Status.Latency
  82. vs.Status.Latency = latency
  83. return old
  84. }
  85. func (vs *ValidatorState) SetOnline(isOnline bool) {
  86. vs.Status.mtx.Lock()
  87. defer vs.Status.mtx.Unlock()
  88. vs.Status.Online = isOnline
  89. }
  90. // Return the validators pubkey. If it's not yet set, get it from the node
  91. // TODO: proof that it's the node's key
  92. // XXX: Is this necessary? Why would it not be set
  93. func (vs *ValidatorState) PubKey() crypto.PubKey {
  94. if vs.Config.Validator.PubKey != nil {
  95. return vs.Config.Validator.PubKey
  96. }
  97. var result ctypes.TMResult
  98. _, err := vs.client.Call("status", nil, &result)
  99. if err != nil {
  100. log.Error("Error getting validator pubkey", "addr", vs.Config.RPCAddr, "val", vs.Config.Validator.ID, "error", err)
  101. return nil
  102. }
  103. status := result.(*ctypes.ResultStatus)
  104. vs.Config.Validator.PubKey = status.PubKey
  105. return vs.Config.Validator.PubKey
  106. }
  107. type ValidatorConfig struct {
  108. mtx sync.Mutex
  109. Validator *Validator `json:"validator"`
  110. P2PAddr string `json:"p2p_addr"`
  111. RPCAddr string `json:"rpc_addr"`
  112. Index int `json:"index,omitempty"`
  113. }
  114. // TODO: update p2p address
  115. func (vc *ValidatorConfig) UpdateRPCAddress(rpcAddr string) {
  116. vc.mtx.Lock()
  117. defer vc.mtx.Unlock()
  118. vc.RPCAddr = rpcAddr
  119. }
  120. type ValidatorStatus struct {
  121. mtx sync.Mutex
  122. Online bool `json:"online"`
  123. Latency float64 `json:"latency" wire:"unsafe"`
  124. BlockHeight int `json:"block_height"`
  125. }
  126. //---------------------------------------------------
  127. // utilities
  128. // Unmarshal a json event
  129. func UnmarshalEvent(b json.RawMessage) (string, events.EventData, error) {
  130. var err error
  131. result := new(ctypes.TMResult)
  132. wire.ReadJSONPtr(result, b, &err)
  133. if err != nil {
  134. return "", nil, err
  135. }
  136. event, ok := (*result).(*ctypes.ResultEvent)
  137. if !ok {
  138. return "", nil, nil // TODO: handle non-event messages (ie. return from subscribe/unsubscribe)
  139. // fmt.Errorf("Result is not type *ctypes.ResultEvent. Got %v", reflect.TypeOf(*result))
  140. }
  141. return event.Name, event.Data, nil
  142. }