Browse Source

signer interface for validators

pull/169/head
Ethan Buchman 9 years ago
parent
commit
28ec3d48fa
4 changed files with 54 additions and 20 deletions
  1. +13
    -6
      node/node.go
  2. +1
    -1
      node/node_test.go
  3. +39
    -12
      types/priv_validator.go
  4. +1
    -1
      types/vote_set_test.go

+ 13
- 6
node/node.go View File

@ -41,7 +41,15 @@ type Node struct {
privKey crypto.PrivKeyEd25519 privKey crypto.PrivKeyEd25519
} }
func NewNode() *Node {
func NewNodeDefaultPrivVal() *Node {
// Get PrivValidator
privValidatorFile := config.GetString("priv_validator_file")
privValidator := types.LoadOrGenPrivValidator(privValidatorFile)
return NewNode(privValidator)
}
func NewNode(privValidator *types.PrivValidator) *Node {
// Get BlockStore // Get BlockStore
blockStoreDB := dbm.GetDB("blockstore") blockStoreDB := dbm.GetDB("blockstore")
blockStore := bc.NewBlockStore(blockStoreDB) blockStore := bc.NewBlockStore(blockStoreDB)
@ -58,10 +66,6 @@ func NewNode() *Node {
// add the chainid to the global config // add the chainid to the global config
config.Set("chain_id", state.ChainID) config.Set("chain_id", state.ChainID)
// Get PrivValidator
privValidatorFile := config.GetString("priv_validator_file")
privValidator := types.LoadOrGenPrivValidator(privValidatorFile)
// Generate node PrivKey // Generate node PrivKey
privKey := crypto.GenPrivKeyEd25519() privKey := crypto.GenPrivKeyEd25519()
@ -249,6 +253,9 @@ func makeNodeInfo(sw *p2p.Switch, privKey crypto.PrivKeyEd25519) *p2p.NodeInfo {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Users wishing to use an external signer for their validators
// should fork tendermint/tendermint and implement RunNode to
// load their custom priv validator and call NewNode(privVal)
func RunNode() { func RunNode() {
// Wait until the genesis doc becomes available // Wait until the genesis doc becomes available
@ -274,7 +281,7 @@ func RunNode() {
} }
// Create & start node // Create & start node
n := NewNode()
n := NewNodeDefaultPrivVal()
l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), config.GetBool("skip_upnp")) l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), config.GetBool("skip_upnp"))
n.AddListener(l) n.AddListener(l)
err := n.Start() err := n.Start()


+ 1
- 1
node/node_test.go View File

@ -24,7 +24,7 @@ func TestNodeStartStop(t *testing.T) {
time.Sleep(time.Second * 2) time.Sleep(time.Second * 2)
// Create & start node // Create & start node
n := NewNode()
n := NewNodeDefaultPrivVal()
l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), config.GetBool("skip_upnp")) l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), config.GetBool("skip_upnp"))
n.AddListener(l) n.AddListener(l)
n.Start() n.Start()


+ 39
- 12
types/priv_validator.go View File

@ -35,12 +35,15 @@ func voteToStep(vote *Vote) int8 {
} }
type PrivValidator struct { type PrivValidator struct {
Address []byte `json:"address"`
PubKey crypto.PubKeyEd25519 `json:"pub_key"`
PrivKey crypto.PrivKeyEd25519 `json:"priv_key"`
LastHeight int `json:"last_height"`
LastRound int `json:"last_round"`
LastStep int8 `json:"last_step"`
Address []byte `json:"address"`
PubKey crypto.PubKeyEd25519 `json:"pub_key"`
LastHeight int `json:"last_height"`
LastRound int `json:"last_round"`
LastStep int8 `json:"last_step"`
// PrivKey should be empty if a Signer other than the default is being used.
PrivKey crypto.PrivKeyEd25519 `json:"priv_key"`
signer Signer
// For persistence. // For persistence.
// Overloaded for testing. // Overloaded for testing.
@ -48,6 +51,32 @@ type PrivValidator struct {
mtx sync.Mutex mtx sync.Mutex
} }
// XXX: This is used to sign votes.
// It is the caller's duty to verify the msg before calling Sign,
// eg. to avoid double signing.
// Currently, the only callers are SignVote and SignProposal
type Signer interface {
Sign(msg []byte) crypto.SignatureEd25519
}
// Implements Signer
type DefaultSigner struct {
priv crypto.PrivKeyEd25519
}
func NewDefaultSigner(priv crypto.PrivKeyEd25519) *DefaultSigner {
return &DefaultSigner{priv: priv}
}
// Implements Signer
func (ds *DefaultSigner) Sign(msg []byte) crypto.SignatureEd25519 {
return ds.priv.Sign(msg).(crypto.SignatureEd25519)
}
func (privVal *PrivValidator) SetSigner(s Signer) {
privVal.signer = s
}
// Generates a new validator with private key. // Generates a new validator with private key.
func GenPrivValidator() *PrivValidator { func GenPrivValidator() *PrivValidator {
privKeyBytes := new([64]byte) privKeyBytes := new([64]byte)
@ -63,6 +92,7 @@ func GenPrivValidator() *PrivValidator {
LastRound: 0, LastRound: 0,
LastStep: stepNone, LastStep: stepNone,
filePath: "", filePath: "",
signer: NewDefaultSigner(privKey),
} }
} }
@ -76,6 +106,7 @@ func LoadPrivValidator(filePath string) *PrivValidator {
Exit(Fmt("Error reading PrivValidator from %v: %v\n", filePath, err)) Exit(Fmt("Error reading PrivValidator from %v: %v\n", filePath, err))
} }
privVal.filePath = filePath privVal.filePath = filePath
privVal.signer = NewDefaultSigner(privVal.PrivKey)
return privVal return privVal
} }
@ -145,14 +176,10 @@ func (privVal *PrivValidator) SignVote(chainID string, vote *Vote) error {
privVal.save() privVal.save()
// Sign // Sign
privVal.SignVoteUnsafe(chainID, vote)
vote.Signature = privVal.signer.Sign(SignBytes(chainID, vote))
return nil return nil
} }
func (privVal *PrivValidator) SignVoteUnsafe(chainID string, vote *Vote) {
vote.Signature = privVal.PrivKey.Sign(SignBytes(chainID, vote)).(crypto.SignatureEd25519)
}
func (privVal *PrivValidator) SignProposal(chainID string, proposal *Proposal) error { func (privVal *PrivValidator) SignProposal(chainID string, proposal *Proposal) error {
privVal.mtx.Lock() privVal.mtx.Lock()
defer privVal.mtx.Unlock() defer privVal.mtx.Unlock()
@ -167,7 +194,7 @@ func (privVal *PrivValidator) SignProposal(chainID string, proposal *Proposal) e
privVal.save() privVal.save()
// Sign // Sign
proposal.Signature = privVal.PrivKey.Sign(SignBytes(chainID, proposal)).(crypto.SignatureEd25519)
proposal.Signature = privVal.signer.Sign(SignBytes(chainID, proposal))
return nil return nil
} else { } else {
return errors.New(fmt.Sprintf("Attempt of duplicate signing of proposal: Height %v, Round %v", proposal.Height, proposal.Round)) return errors.New(fmt.Sprintf("Attempt of duplicate signing of proposal: Height %v, Round %v", proposal.Height, proposal.Round))


+ 1
- 1
types/vote_set_test.go View File

@ -60,7 +60,7 @@ func withBlockPartsHeader(vote *Vote, blockPartsHeader PartSetHeader) *Vote {
} }
func signAddVote(privVal *PrivValidator, vote *Vote, voteSet *VoteSet) (bool, error) { func signAddVote(privVal *PrivValidator, vote *Vote, voteSet *VoteSet) (bool, error) {
privVal.SignVoteUnsafe(config.GetString("chain_id"), vote)
vote.Signature = privVal.signer.Sign(SignBytes(config.GetString("chain_id"), vote))
added, _, err := voteSet.AddByAddress(privVal.Address, vote) added, _, err := voteSet.AddByAddress(privVal.Address, vote)
return added, err return added, err
} }


Loading…
Cancel
Save