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.

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