diff --git a/Makefile b/Makefile index c73e77194..61adee45a 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,10 @@ all: test install TMROOT = $${TMROOT:-$$HOME/.tendermint} +define NEWLINE + + +endef install: get_deps go install github.com/tendermint/tendermint/cmd/tendermint @@ -29,10 +33,11 @@ draw_deps: goviz -i github.com/tendermint/tendermint/cmd/tendermint | dot -Tpng -o huge.png list_deps: - go list -f '{{join .Deps "\n"}}' github.com/tendermint/tendermint/... | xargs go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' + go list -f '{{join .Deps "\n"}}' github.com/tendermint/tendermint/... | sort | uniq | xargs go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' get_deps: go get -d github.com/tendermint/tendermint/... + go list -f '{{join .TestImports "\n"}}' github.com/tendermint/tendermint/... | sort | uniq | xargs go get revision: -echo `git rev-parse --verify HEAD` > $(TMROOT)/revision diff --git a/node/node.go b/node/node.go index 9f64bfa82..d3760e042 100644 --- a/node/node.go +++ b/node/node.go @@ -41,7 +41,15 @@ type Node struct { 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 blockStoreDB := dbm.GetDB("blockstore") blockStore := bc.NewBlockStore(blockStoreDB) @@ -58,10 +66,6 @@ func NewNode() *Node { // add the chainid to the global config config.Set("chain_id", state.ChainID) - // Get PrivValidator - privValidatorFile := config.GetString("priv_validator_file") - privValidator := types.LoadOrGenPrivValidator(privValidatorFile) - // Generate node PrivKey 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() { // Wait until the genesis doc becomes available @@ -274,7 +281,7 @@ func RunNode() { } // Create & start node - n := NewNode() + n := NewNodeDefaultPrivVal() l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), config.GetBool("skip_upnp")) n.AddListener(l) err := n.Start() diff --git a/node/node_test.go b/node/node_test.go index 135d5444b..e0898a979 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -24,7 +24,7 @@ func TestNodeStartStop(t *testing.T) { time.Sleep(time.Second * 2) // Create & start node - n := NewNode() + n := NewNodeDefaultPrivVal() l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), config.GetBool("skip_upnp")) n.AddListener(l) n.Start() diff --git a/types/priv_validator.go b/types/priv_validator.go index 3551082c8..78b95c6af 100644 --- a/types/priv_validator.go +++ b/types/priv_validator.go @@ -35,12 +35,15 @@ func voteToStep(vote *Vote) int8 { } type PrivValidator struct { - Address []byte `json:"address"` - PubKey crypto.PubKey `json:"pub_key"` - PrivKey crypto.PrivKey `json:"priv_key"` - LastHeight int `json:"last_height"` - LastRound int `json:"last_round"` - LastStep int8 `json:"last_step"` + Address []byte `json:"address"` + PubKey crypto.PubKey `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.PrivKey `json:"priv_key"` + Signer // For persistence. // Overloaded for testing. @@ -48,6 +51,32 @@ type PrivValidator struct { mtx sync.Mutex } +// 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.Signature +} + +// Implements Signer +type DefaultSigner struct { + priv crypto.PrivKey +} + +func NewDefaultSigner(priv crypto.PrivKey) *DefaultSigner { + return &DefaultSigner{priv: priv} +} + +// Implements Signer +func (ds *DefaultSigner) Sign(msg []byte) crypto.Signature { + return ds.priv.Sign(msg) +} + +func (privVal *PrivValidator) SetSigner(s Signer) { + privVal.Signer = s +} + // Generates a new validator with private key. func GenPrivValidator() *PrivValidator { privKeyBytes := new([64]byte) @@ -63,6 +92,7 @@ func GenPrivValidator() *PrivValidator { LastRound: 0, LastStep: stepNone, filePath: "", + Signer: NewDefaultSigner(privKey), } } @@ -76,6 +106,7 @@ func LoadPrivValidator(filePath string) *PrivValidator { Exit(Fmt("Error reading PrivValidator from %v: %v\n", filePath, err)) } privVal.filePath = filePath + privVal.Signer = NewDefaultSigner(privVal.PrivKey) return privVal } @@ -145,14 +176,10 @@ func (privVal *PrivValidator) SignVote(chainID string, vote *Vote) error { privVal.save() // Sign - privVal.SignVoteUnsafe(chainID, vote) + vote.Signature = privVal.Sign(SignBytes(chainID, vote)).(crypto.SignatureEd25519) 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 { privVal.mtx.Lock() defer privVal.mtx.Unlock() @@ -167,7 +194,7 @@ func (privVal *PrivValidator) SignProposal(chainID string, proposal *Proposal) e privVal.save() // Sign - proposal.Signature = privVal.PrivKey.Sign(SignBytes(chainID, proposal)).(crypto.SignatureEd25519) + proposal.Signature = privVal.Sign(SignBytes(chainID, proposal)).(crypto.SignatureEd25519) return nil } else { return errors.New(fmt.Sprintf("Attempt of duplicate signing of proposal: Height %v, Round %v", proposal.Height, proposal.Round)) diff --git a/types/vote_set_test.go b/types/vote_set_test.go index 6bbf05440..e4da14169 100644 --- a/types/vote_set_test.go +++ b/types/vote_set_test.go @@ -5,6 +5,7 @@ import ( . "github.com/tendermint/go-common" . "github.com/tendermint/go-common/test" + "github.com/tendermint/go-crypto" _ "github.com/tendermint/tendermint/config/tendermint_test" "testing" @@ -52,7 +53,7 @@ func withBlockPartsHeader(vote *Vote, blockPartsHeader PartSetHeader) *Vote { } func signAddVote(privVal *PrivValidator, vote *Vote, voteSet *VoteSet) (bool, error) { - privVal.SignVoteUnsafe(config.GetString("chain_id"), vote) + vote.Signature = privVal.Sign(SignBytes(config.GetString("chain_id"), vote)).(crypto.SignatureEd25519) added, _, err := voteSet.AddByAddress(privVal.Address, vote) return added, err }