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.

246 lines
6.5 KiB

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