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.

250 lines
6.5 KiB

  1. package types
  2. import (
  3. "bytes"
  4. "fmt"
  5. "reflect"
  6. "time"
  7. abci "github.com/tendermint/tendermint/abci/types"
  8. "github.com/tendermint/tendermint/crypto"
  9. "github.com/tendermint/tendermint/crypto/ed25519"
  10. "github.com/tendermint/tendermint/crypto/secp256k1"
  11. )
  12. //-------------------------------------------------------
  13. // Use strings to distinguish types in ABCI messages
  14. const (
  15. ABCIEvidenceTypeDuplicateVote = "duplicate/vote"
  16. ABCIEvidenceTypeMockGood = "mock/good"
  17. )
  18. const (
  19. ABCIPubKeyTypeEd25519 = "ed25519"
  20. ABCIPubKeyTypeSecp256k1 = "secp256k1"
  21. )
  22. //-------------------------------------------------------
  23. // TM2PB is used for converting Tendermint ABCI to protobuf ABCI.
  24. // UNSTABLE
  25. var TM2PB = tm2pb{}
  26. type tm2pb struct{}
  27. func (tm2pb) Header(header *Header) abci.Header {
  28. return abci.Header{
  29. ChainID: header.ChainID,
  30. Height: header.Height,
  31. Time: header.Time,
  32. NumTxs: header.NumTxs,
  33. TotalTxs: header.TotalTxs,
  34. LastBlockId: TM2PB.BlockID(header.LastBlockID),
  35. LastCommitHash: header.LastCommitHash,
  36. DataHash: header.DataHash,
  37. ValidatorsHash: header.ValidatorsHash,
  38. ConsensusHash: header.ConsensusHash,
  39. AppHash: header.AppHash,
  40. LastResultsHash: header.LastResultsHash,
  41. EvidenceHash: header.EvidenceHash,
  42. ProposerAddress: header.ProposerAddress,
  43. }
  44. }
  45. func (tm2pb) ValidatorWithoutPubKey(val *Validator) abci.Validator {
  46. return abci.Validator{
  47. Address: val.PubKey.Address(),
  48. Power: val.VotingPower,
  49. }
  50. }
  51. func (tm2pb) BlockID(blockID BlockID) abci.BlockID {
  52. return abci.BlockID{
  53. Hash: blockID.Hash,
  54. PartsHeader: TM2PB.PartSetHeader(blockID.PartsHeader),
  55. }
  56. }
  57. func (tm2pb) PartSetHeader(header PartSetHeader) abci.PartSetHeader {
  58. return abci.PartSetHeader{
  59. Total: int32(header.Total),
  60. Hash: header.Hash,
  61. }
  62. }
  63. // XXX: panics on unknown pubkey type
  64. func (tm2pb) Validator(val *Validator) abci.Validator {
  65. return abci.Validator{
  66. Address: val.PubKey.Address(),
  67. PubKey: TM2PB.PubKey(val.PubKey),
  68. Power: val.VotingPower,
  69. }
  70. }
  71. // XXX: panics on nil or unknown pubkey type
  72. // TODO: add cases when new pubkey types are added to crypto
  73. func (tm2pb) PubKey(pubKey crypto.PubKey) abci.PubKey {
  74. switch pk := pubKey.(type) {
  75. case ed25519.PubKeyEd25519:
  76. return abci.PubKey{
  77. Type: ABCIPubKeyTypeEd25519,
  78. Data: pk[:],
  79. }
  80. case secp256k1.PubKeySecp256k1:
  81. return abci.PubKey{
  82. Type: ABCIPubKeyTypeSecp256k1,
  83. Data: pk[:],
  84. }
  85. default:
  86. panic(fmt.Sprintf("unknown pubkey type: %v %v", pubKey, reflect.TypeOf(pubKey)))
  87. }
  88. }
  89. // XXX: panics on nil or unknown pubkey type
  90. func (tm2pb) Validators(vals *ValidatorSet) []abci.Validator {
  91. validators := make([]abci.Validator, vals.Size())
  92. for i, val := range vals.Validators {
  93. validators[i] = TM2PB.Validator(val)
  94. }
  95. return validators
  96. }
  97. func (tm2pb) ConsensusParams(params *ConsensusParams) *abci.ConsensusParams {
  98. return &abci.ConsensusParams{
  99. BlockSize: &abci.BlockSize{
  100. MaxBytes: int32(params.BlockSize.MaxBytes),
  101. MaxTxs: int32(params.BlockSize.MaxTxs),
  102. MaxGas: params.BlockSize.MaxGas,
  103. },
  104. TxSize: &abci.TxSize{
  105. MaxBytes: int32(params.TxSize.MaxBytes),
  106. MaxGas: params.TxSize.MaxGas,
  107. },
  108. BlockGossip: &abci.BlockGossip{
  109. BlockPartSizeBytes: int32(params.BlockGossip.BlockPartSizeBytes),
  110. },
  111. }
  112. }
  113. // ABCI Evidence includes information from the past that's not included in the evidence itself
  114. // so Evidence types stays compact.
  115. // XXX: panics on nil or unknown pubkey type
  116. func (tm2pb) Evidence(ev Evidence, valSet *ValidatorSet, evTime time.Time) abci.Evidence {
  117. _, val := valSet.GetByAddress(ev.Address())
  118. if val == nil {
  119. // should already have checked this
  120. panic(val)
  121. }
  122. // set type
  123. var evType string
  124. switch ev.(type) {
  125. case *DuplicateVoteEvidence:
  126. evType = ABCIEvidenceTypeDuplicateVote
  127. case MockGoodEvidence:
  128. // XXX: not great to have test types in production paths ...
  129. evType = ABCIEvidenceTypeMockGood
  130. default:
  131. panic(fmt.Sprintf("Unknown evidence type: %v %v", ev, reflect.TypeOf(ev)))
  132. }
  133. return abci.Evidence{
  134. Type: evType,
  135. Validator: TM2PB.ValidatorWithoutPubKey(val),
  136. Height: ev.Height(),
  137. Time: evTime,
  138. TotalVotingPower: valSet.TotalVotingPower(),
  139. }
  140. }
  141. // XXX: panics on nil or unknown pubkey type
  142. func (tm2pb) ValidatorFromPubKeyAndPower(pubkey crypto.PubKey, power int64) abci.Validator {
  143. pubkeyABCI := TM2PB.PubKey(pubkey)
  144. return abci.Validator{
  145. Address: pubkey.Address(),
  146. PubKey: pubkeyABCI,
  147. Power: power,
  148. }
  149. }
  150. //----------------------------------------------------------------------------
  151. // PB2TM is used for converting protobuf ABCI to Tendermint ABCI.
  152. // UNSTABLE
  153. var PB2TM = pb2tm{}
  154. type pb2tm struct{}
  155. func (pb2tm) PubKey(pubKey abci.PubKey) (crypto.PubKey, error) {
  156. // TODO: define these in crypto and use them
  157. sizeEd := 32
  158. sizeSecp := 33
  159. switch pubKey.Type {
  160. case ABCIPubKeyTypeEd25519:
  161. if len(pubKey.Data) != sizeEd {
  162. return nil, fmt.Errorf("Invalid size for PubKeyEd25519. Got %d, expected %d", len(pubKey.Data), sizeEd)
  163. }
  164. var pk ed25519.PubKeyEd25519
  165. copy(pk[:], pubKey.Data)
  166. return pk, nil
  167. case ABCIPubKeyTypeSecp256k1:
  168. if len(pubKey.Data) != sizeSecp {
  169. return nil, fmt.Errorf("Invalid size for PubKeyEd25519. Got %d, expected %d", len(pubKey.Data), sizeSecp)
  170. }
  171. var pk secp256k1.PubKeySecp256k1
  172. copy(pk[:], pubKey.Data)
  173. return pk, nil
  174. default:
  175. return nil, fmt.Errorf("Unknown pubkey type %v", pubKey.Type)
  176. }
  177. }
  178. func (pb2tm) Validators(vals []abci.Validator) ([]*Validator, error) {
  179. tmVals := make([]*Validator, len(vals))
  180. for i, v := range vals {
  181. pub, err := PB2TM.PubKey(v.PubKey)
  182. if err != nil {
  183. return nil, err
  184. }
  185. // If the app provided an address too, it must match.
  186. // This is just a sanity check.
  187. if len(v.Address) > 0 {
  188. if !bytes.Equal(pub.Address(), v.Address) {
  189. return nil, fmt.Errorf("Validator.Address (%X) does not match PubKey.Address (%X)",
  190. v.Address, pub.Address())
  191. }
  192. }
  193. tmVals[i] = &Validator{
  194. Address: pub.Address(),
  195. PubKey: pub,
  196. VotingPower: v.Power,
  197. }
  198. }
  199. return tmVals, nil
  200. }
  201. func (pb2tm) ConsensusParams(csp *abci.ConsensusParams) ConsensusParams {
  202. return ConsensusParams{
  203. BlockSize: BlockSize{
  204. MaxBytes: int(csp.BlockSize.MaxBytes), // XXX
  205. MaxTxs: int(csp.BlockSize.MaxTxs), // XXX
  206. MaxGas: csp.BlockSize.MaxGas,
  207. },
  208. TxSize: TxSize{
  209. MaxBytes: int(csp.TxSize.MaxBytes), // XXX
  210. MaxGas: csp.TxSize.MaxGas,
  211. },
  212. BlockGossip: BlockGossip{
  213. BlockPartSizeBytes: int(csp.BlockGossip.BlockPartSizeBytes), // XXX
  214. },
  215. // TODO: EvidenceParams: EvidenceParams{
  216. // MaxAge: int(csp.Evidence.MaxAge), // XXX
  217. // },
  218. }
  219. }