# ADR 008: PrivValidator

## Context

The current PrivValidator is monolithic and isn't easily reuseable by alternative signers.

For instance, see https://github.com/tendermint/tendermint/issues/673

The goal is to have a clean PrivValidator interface like:

```
type PrivValidator interface {
	Address() data.Bytes
	PubKey() crypto.PubKey

	SignVote(chainID string, vote *types.Vote) error
	SignProposal(chainID string, proposal *types.Proposal) error
	SignHeartbeat(chainID string, heartbeat *types.Heartbeat) error
}
```

It should also be easy to re-use the LastSignedInfo logic to avoid double signing.

## Decision

Tendermint node's should support only two in-process PrivValidator implementations:

- PrivValidatorUnencrypted uses an unencrypted private key in a "priv_validator.json" file - no configuration required (just `tendermint init`).
- PrivValidatorSocket uses a socket to send signing requests to another process - user is responsible for starting that process themselves.

The PrivValidatorSocket address can be provided via flags at the command line -
doing so will cause Tendermint to ignore any "priv_validator.json" file and to attempt
to connect over the socket.

In addition, Tendermint will provide implementations that can be run in that external process.
These include:

- PrivValidatorEncrypted uses an encrypted private key persisted to disk - user must enter password to decrypt key when process is started.
- PrivValidatorLedger uses a Ledger Nano S to handle all signing.

What follows are descriptions of useful types

### Signer

```
type Signer interface {
	Sign(msg []byte) (crypto.Signature, error)
}
```

Signer signs a message. It can also return an error.

### ValidatorID


ValidatorID is just the Address and PubKey

```
type ValidatorID struct {
	Address data.Bytes    `json:"address"`
	PubKey  crypto.PubKey `json:"pub_key"`
}
```

### LastSignedInfo

LastSignedInfo tracks the last thing we signed:

```
type LastSignedInfo struct {
	Height    int64            `json:"height"`
	Round     int              `json:"round"`
	Step      int8             `json:"step"`
	Signature crypto.Signature `json:"signature,omitempty"` // so we dont lose signatures
	SignBytes data.Bytes       `json:"signbytes,omitempty"` // so we dont lose signatures
}
```

It exposes methods for signing votes and proposals using a `Signer`.

This allows it to easily be reused by developers implemented their own PrivValidator.

### PrivValidatorUnencrypted

```
type PrivValidatorUnencrypted struct {
	ID             types.ValidatorID `json:"id"`
	PrivKey        PrivKey           `json:"priv_key"`
	LastSignedInfo *LastSignedInfo   `json:"last_signed_info"`
}
```

Has the same structure as currently, but broken up into sub structs.

Note the LastSignedInfo is mutated in place every time we sign.

### PrivValidatorJSON

The "priv_validator.json" file supports only the PrivValidatorUnencrypted type.

It unmarshals into PrivValidatorJSON, which is used as the default PrivValidator type.
It wraps the PrivValidatorUnencrypted and persists it to disk after every signature.

## Status

Proposed.

## Consequences

### Positive

- Cleaner separation of components enabling re-use.

### Negative

- More files - led to creation of new directory.

### Neutral

