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.

118 lines
3.2 KiB

  1. # ADR 008: PrivValidator
  2. ## Context
  3. The current PrivValidator is monolithic and isn't easily reuseable by alternative signers.
  4. For instance, see https://github.com/tendermint/tendermint/issues/673
  5. The goal is to have a clean PrivValidator interface like:
  6. ``
  7. type PrivValidator interface {
  8. Address() data.Bytes
  9. PubKey() crypto.PubKey
  10. SignVote(chainID string, vote *types.Vote) error
  11. SignProposal(chainID string, proposal *types.Proposal) error
  12. SignHeartbeat(chainID string, heartbeat *types.Heartbeat) error
  13. }
  14. ```
  15. It should also be easy to re-use the LastSignedInfo logic to avoid double signing.
  16. ## Decision
  17. Tendermint node's should support only two in-process PrivValidator implementations:
  18. - PrivValidatorUnencrypted uses an unencrypted private key in a "priv_validator.json" file - no configuration required (just `tendermint init`).
  19. - PrivValidatorSocket uses a socket to send signing requests to another process - user is responsible for starting that process themselves.
  20. The PrivValidatorSocket address can be provided via flags at the command line -
  21. doing so will cause Tendermint to ignore any "priv_validator.json" file and to attempt
  22. to connect over the socket.
  23. In addition, Tendermint will provide implementations that can be run in that external process.
  24. These include:
  25. - PrivValidatorEncrypted uses an encrypted private key persisted to disk - user must enter password to decrypt key when process is started.
  26. - PrivValidatorLedger uses a Ledger Nano S to handle all signing.
  27. What follows are descriptions of useful types
  28. ### Signer
  29. ```
  30. type Signer interface {
  31. Sign(msg []byte) (crypto.Signature, error)
  32. }
  33. ```
  34. Signer signs a message. It can also return an error.
  35. ### ValidatorID
  36. ValidatorID is just the Address and PubKey
  37. ```
  38. type ValidatorID struct {
  39. Address data.Bytes `json:"address"`
  40. PubKey crypto.PubKey `json:"pub_key"`
  41. }
  42. ### LastSignedInfo
  43. LastSignedInfo tracks the last thing we signed:
  44. ```
  45. type LastSignedInfo struct {
  46. Height int64 `json:"height"`
  47. Round int `json:"round"`
  48. Step int8 `json:"step"`
  49. Signature crypto.Signature `json:"signature,omitempty"` // so we dont lose signatures
  50. SignBytes data.Bytes `json:"signbytes,omitempty"` // so we dont lose signatures
  51. }
  52. ```
  53. It exposes methods for signing votes and proposals using a `Signer`.
  54. This allows it to easily be reused by developers implemented their own PrivValidator.
  55. ### PrivValidatorUnencrypted
  56. ```
  57. type PrivValidatorUnencrypted struct {
  58. ID types.ValidatorID `json:"id"`
  59. PrivKey PrivKey `json:"priv_key"`
  60. LastSignedInfo *LastSignedInfo `json:"last_signed_info"`
  61. }
  62. ```
  63. Has the same structure as currently, but broken up into sub structs.
  64. Note the LastSignedInfo is mutated in place every time we sign.
  65. ### PrivValidatorJSON
  66. The "priv_validator.json" file supports only the PrivValidatorUnencrypted type.
  67. It unmarshals into PrivValidatorJSON, which is used as the default PrivValidator type.
  68. It wraps the PrivValidatorUnencrypted and persists it to disk after every signature.
  69. ## Status
  70. Proposed.
  71. ## Consequences
  72. ### Positive
  73. - Cleaner separation of components enabling re-use.
  74. ### Negative
  75. - More files - led to creation of new directory.
  76. ### Neutral