mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-01 23:51:21 +00:00
PrivValidator interface
This commit is contained in:
parent
abe912c610
commit
fd1b0b997a
@ -30,7 +30,7 @@ func initFiles(cmd *cobra.Command, args []string) {
|
||||
ChainID: cmn.Fmt("test-chain-%v", cmn.RandStr(6)),
|
||||
}
|
||||
genDoc.Validators = []types.GenesisValidator{types.GenesisValidator{
|
||||
PubKey: privValidator.PubKey,
|
||||
PubKey: privValidator.PubKey(),
|
||||
Power: 10,
|
||||
}}
|
||||
|
||||
|
@ -46,7 +46,7 @@ func resetPrivValidator(cmd *cobra.Command, args []string) {
|
||||
|
||||
func resetPrivValidatorLocal(privValFile string, logger log.Logger) {
|
||||
// Get PrivValidator
|
||||
var privValidator *types.PrivValidator
|
||||
var privValidator types.PrivValidator
|
||||
if _, err := os.Stat(privValFile); err == nil {
|
||||
privValidator = types.LoadPrivValidator(privValFile)
|
||||
privValidator.Reset()
|
||||
|
@ -41,9 +41,9 @@ func AddNodeFlags(cmd *cobra.Command) {
|
||||
|
||||
// FuncSignerAndApp takes a config and returns a PrivValidator and ClientCreator.
|
||||
// It allows other projects to make Tendermint binaries with custom signers and applications.
|
||||
type FuncSignerAndApp func(*cfg.Config) (*types.PrivValidator, proxy.ClientCreator)
|
||||
type FuncSignerAndApp func(*cfg.Config) (types.PrivValidator, proxy.ClientCreator)
|
||||
|
||||
func DefaultSignerAndApp(config *cfg.Config) (*types.PrivValidator, proxy.ClientCreator) {
|
||||
func DefaultSignerAndApp(config *cfg.Config) (types.PrivValidator, proxy.ClientCreator) {
|
||||
privValidator := types.LoadOrGenPrivValidator(config.PrivValidatorFile())
|
||||
clientCreator := proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir())
|
||||
return privValidator, clientCreator
|
||||
|
@ -47,7 +47,7 @@ func testnetFiles(cmd *cobra.Command, args []string) {
|
||||
privValFile := path.Join(dataDir, mach, "priv_validator.json")
|
||||
privVal := types.LoadPrivValidator(privValFile)
|
||||
genVals[i] = types.GenesisValidator{
|
||||
PubKey: privVal.PubKey,
|
||||
PubKey: privVal.PubKey(),
|
||||
Power: 1,
|
||||
Name: mach,
|
||||
}
|
||||
|
@ -180,14 +180,6 @@ func (ti *timeoutInfo) String() string {
|
||||
return fmt.Sprintf("%v ; %d/%d %v", ti.Duration, ti.Height, ti.Round, ti.Step)
|
||||
}
|
||||
|
||||
// PrivValidator is a validator that can sign votes and proposals.
|
||||
type PrivValidator interface {
|
||||
GetAddress() []byte
|
||||
SignVote(chainID string, vote *types.Vote) error
|
||||
SignProposal(chainID string, proposal *types.Proposal) error
|
||||
SignHeartbeat(chainID string, heartbeat *types.Heartbeat) error
|
||||
}
|
||||
|
||||
// ConsensusState handles execution of the consensus algorithm.
|
||||
// It processes votes and proposals, and upon reaching agreement,
|
||||
// commits blocks to the chain and executes them against the application.
|
||||
@ -197,7 +189,7 @@ type ConsensusState struct {
|
||||
|
||||
// config details
|
||||
config *cfg.ConsensusConfig
|
||||
privValidator PrivValidator // for signing votes
|
||||
privValidator types.PrivValidator // for signing votes
|
||||
|
||||
// services for creating and executing blocks
|
||||
proxyAppConn proxy.AppConnConsensus
|
||||
@ -308,7 +300,7 @@ func (cs *ConsensusState) GetValidators() (int, []*types.Validator) {
|
||||
}
|
||||
|
||||
// SetPrivValidator sets the private validator account for signing votes.
|
||||
func (cs *ConsensusState) SetPrivValidator(priv PrivValidator) {
|
||||
func (cs *ConsensusState) SetPrivValidator(priv types.PrivValidator) {
|
||||
cs.mtx.Lock()
|
||||
defer cs.mtx.Unlock()
|
||||
cs.privValidator = priv
|
||||
@ -825,7 +817,7 @@ func (cs *ConsensusState) needProofBlock(height int) bool {
|
||||
|
||||
func (cs *ConsensusState) proposalHeartbeat(height, round int) {
|
||||
counter := 0
|
||||
addr := cs.privValidator.GetAddress()
|
||||
addr := cs.privValidator.Address()
|
||||
valIndex, v := cs.Validators.GetByAddress(addr)
|
||||
if v == nil {
|
||||
// not a validator
|
||||
@ -886,7 +878,7 @@ func (cs *ConsensusState) enterPropose(height int, round int) {
|
||||
|
||||
if !cs.isProposer() {
|
||||
cs.Logger.Info("enterPropose: Not our turn to propose", "proposer", cs.Validators.GetProposer().Address, "privValidator", cs.privValidator)
|
||||
if cs.Validators.HasAddress(cs.privValidator.GetAddress()) {
|
||||
if cs.Validators.HasAddress(cs.privValidator.Address()) {
|
||||
cs.Logger.Debug("This node is a validator")
|
||||
} else {
|
||||
cs.Logger.Debug("This node is not a validator")
|
||||
@ -899,7 +891,7 @@ func (cs *ConsensusState) enterPropose(height int, round int) {
|
||||
}
|
||||
|
||||
func (cs *ConsensusState) isProposer() bool {
|
||||
return bytes.Equal(cs.Validators.GetProposer().Address, cs.privValidator.GetAddress())
|
||||
return bytes.Equal(cs.Validators.GetProposer().Address, cs.privValidator.Address())
|
||||
}
|
||||
|
||||
func (cs *ConsensusState) defaultDecideProposal(height, round int) {
|
||||
@ -1444,7 +1436,7 @@ func (cs *ConsensusState) tryAddVote(vote *types.Vote, peerKey string) error {
|
||||
if err == ErrVoteHeightMismatch {
|
||||
return err
|
||||
} else if _, ok := err.(*types.ErrVoteConflictingVotes); ok {
|
||||
if bytes.Equal(vote.ValidatorAddress, cs.privValidator.GetAddress()) {
|
||||
if bytes.Equal(vote.ValidatorAddress, cs.privValidator.Address()) {
|
||||
cs.Logger.Error("Found conflicting vote from ourselves. Did you unsafe_reset a validator?", "height", vote.Height, "round", vote.Round, "type", vote.Type)
|
||||
return err
|
||||
}
|
||||
@ -1573,7 +1565,7 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerKey string) (added bool,
|
||||
}
|
||||
|
||||
func (cs *ConsensusState) signVote(type_ byte, hash []byte, header types.PartSetHeader) (*types.Vote, error) {
|
||||
addr := cs.privValidator.GetAddress()
|
||||
addr := cs.privValidator.Address()
|
||||
valIndex, _ := cs.Validators.GetByAddress(addr)
|
||||
vote := &types.Vote{
|
||||
ValidatorAddress: addr,
|
||||
@ -1590,7 +1582,7 @@ func (cs *ConsensusState) signVote(type_ byte, hash []byte, header types.PartSet
|
||||
// sign the vote and publish on internalMsgQueue
|
||||
func (cs *ConsensusState) signAddVote(type_ byte, hash []byte, header types.PartSetHeader) *types.Vote {
|
||||
// if we don't have a key or we're not in the validator set, do nothing
|
||||
if cs.privValidator == nil || !cs.Validators.HasAddress(cs.privValidator.GetAddress()) {
|
||||
if cs.privValidator == nil || !cs.Validators.HasAddress(cs.privValidator.Address()) {
|
||||
return nil
|
||||
}
|
||||
vote, err := cs.signVote(type_, hash, header)
|
||||
|
14
node/node.go
14
node/node.go
@ -38,8 +38,8 @@ type Node struct {
|
||||
|
||||
// config
|
||||
config *cfg.Config
|
||||
genesisDoc *types.GenesisDoc // initial validator set
|
||||
privValidator *types.PrivValidator // local node's validator key
|
||||
genesisDoc *types.GenesisDoc // initial validator set
|
||||
privValidator types.PrivValidator // local node's validator key
|
||||
|
||||
// network
|
||||
privKey crypto.PrivKeyEd25519 // local node's p2p key
|
||||
@ -65,7 +65,7 @@ func NewNodeDefault(config *cfg.Config, logger log.Logger) *Node {
|
||||
proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), logger)
|
||||
}
|
||||
|
||||
func NewNode(config *cfg.Config, privValidator *types.PrivValidator, clientCreator proxy.ClientCreator, logger log.Logger) *Node {
|
||||
func NewNode(config *cfg.Config, privValidator types.PrivValidator, clientCreator proxy.ClientCreator, logger log.Logger) *Node {
|
||||
// Get BlockStore
|
||||
blockStoreDB := dbm.NewDB("blockstore", config.DBBackend, config.DBDir())
|
||||
blockStore := bc.NewBlockStore(blockStoreDB)
|
||||
@ -119,13 +119,13 @@ func NewNode(config *cfg.Config, privValidator *types.PrivValidator, clientCreat
|
||||
fastSync := config.FastSync
|
||||
if state.Validators.Size() == 1 {
|
||||
addr, _ := state.Validators.GetByIndex(0)
|
||||
if bytes.Equal(privValidator.Address, addr) {
|
||||
if bytes.Equal(privValidator.Address(), addr) {
|
||||
fastSync = false
|
||||
}
|
||||
}
|
||||
|
||||
// Log whether this node is a validator or an observer
|
||||
if state.Validators.HasAddress(privValidator.Address) {
|
||||
if state.Validators.HasAddress(privValidator.PubKey().Address()) {
|
||||
consensusLogger.Info("This node is a validator")
|
||||
} else {
|
||||
consensusLogger.Info("This node is not a validator")
|
||||
@ -314,7 +314,7 @@ func (n *Node) ConfigureRPC() {
|
||||
rpccore.SetConsensusState(n.consensusState)
|
||||
rpccore.SetMempool(n.mempoolReactor.Mempool)
|
||||
rpccore.SetSwitch(n.sw)
|
||||
rpccore.SetPubKey(n.privValidator.PubKey)
|
||||
rpccore.SetPubKey(n.privValidator.PubKey())
|
||||
rpccore.SetGenesisDoc(n.genesisDoc)
|
||||
rpccore.SetAddrBook(n.addrBook)
|
||||
rpccore.SetProxyAppQuery(n.proxyApp.Query())
|
||||
@ -385,7 +385,7 @@ func (n *Node) EventSwitch() types.EventSwitch {
|
||||
}
|
||||
|
||||
// XXX: for convenience
|
||||
func (n *Node) PrivValidator() *types.PrivValidator {
|
||||
func (n *Node) PrivValidator() types.PrivValidator {
|
||||
return n.privValidator
|
||||
}
|
||||
|
||||
|
@ -46,38 +46,43 @@ type Signer interface {
|
||||
// DefaultSigner implements Signer.
|
||||
// It uses a standard crypto.PrivKey.
|
||||
type DefaultSigner struct {
|
||||
priv crypto.PrivKey
|
||||
PrivKey crypto.PrivKey `json:"priv_key"`
|
||||
}
|
||||
|
||||
// NewDefaultSigner returns an instance of DefaultSigner.
|
||||
func NewDefaultSigner(priv crypto.PrivKey) *DefaultSigner {
|
||||
return &DefaultSigner{priv: priv}
|
||||
return &DefaultSigner{PrivKey: priv}
|
||||
}
|
||||
|
||||
// Sign implements Signer. It signs the byte slice with a private key.
|
||||
func (ds *DefaultSigner) Sign(msg []byte) (crypto.Signature, error) {
|
||||
return ds.priv.Sign(msg), nil
|
||||
return ds.PrivKey.Sign(msg), nil
|
||||
}
|
||||
|
||||
// PubKey implements Signer. It should return the public key that corresponds
|
||||
// to the private key used for signing.
|
||||
func (ds *DefaultSigner) PubKey() crypto.PubKey {
|
||||
return ds.priv.PubKey()
|
||||
return ds.PrivKey.PubKey()
|
||||
}
|
||||
|
||||
// PrivValidator implements the functionality for signing blocks.
|
||||
type PrivValidator struct {
|
||||
Address data.Bytes `json:"address"`
|
||||
PubKey crypto.PubKey `json:"pub_key"`
|
||||
LastHeight int `json:"last_height"`
|
||||
LastRound int `json:"last_round"`
|
||||
LastStep int8 `json:"last_step"`
|
||||
LastSignature crypto.Signature `json:"last_signature,omitempty"` // so we dont lose signatures
|
||||
LastSignBytes data.Bytes `json:"last_signbytes,omitempty"` // so we dont lose signatures
|
||||
type PrivValidator interface {
|
||||
Address() data.Bytes // redundant since .PubKey().Address()
|
||||
PubKey() crypto.PubKey
|
||||
|
||||
// PrivKey should be empty if a Signer other than the default is being used.
|
||||
PrivKey crypto.PrivKey `json:"priv_key"`
|
||||
Signer `json:"-"`
|
||||
SignVote(chainID string, vote *Vote) error
|
||||
SignProposal(chainID string, proposal *Proposal) error
|
||||
SignHeartbeat(chainID string, heartbeat *Heartbeat) error
|
||||
|
||||
Reset()
|
||||
|
||||
SetFile(file string)
|
||||
Save()
|
||||
}
|
||||
|
||||
// DefaultPrivValidator implements the functionality for signing blocks.
|
||||
type DefaultPrivValidator struct {
|
||||
Info PrivValidatorInfo `json:"info"`
|
||||
Signer *DefaultSigner `json:"signer"`
|
||||
|
||||
// For persistence.
|
||||
// Overloaded for testing.
|
||||
@ -85,8 +90,26 @@ type PrivValidator struct {
|
||||
mtx sync.Mutex
|
||||
}
|
||||
|
||||
func LoadOrGenPrivValidator(filePath string) *PrivValidator {
|
||||
var privValidator *PrivValidator
|
||||
func (pv *DefaultPrivValidator) Address() data.Bytes {
|
||||
return pv.Info.Address
|
||||
}
|
||||
|
||||
func (pv *DefaultPrivValidator) PubKey() crypto.PubKey {
|
||||
return pv.Info.PubKey
|
||||
}
|
||||
|
||||
type PrivValidatorInfo struct {
|
||||
Address data.Bytes `json:"address"`
|
||||
PubKey crypto.PubKey `json:"pub_key"`
|
||||
LastHeight int `json:"last_height"`
|
||||
LastRound int `json:"last_round"`
|
||||
LastStep int8 `json:"last_step"`
|
||||
LastSignature crypto.Signature `json:"last_signature,omitempty"` // so we dont lose signatures
|
||||
LastSignBytes data.Bytes `json:"last_signbytes,omitempty"` // so we dont lose signatures
|
||||
}
|
||||
|
||||
func LoadOrGenPrivValidator(filePath string) *DefaultPrivValidator {
|
||||
var privValidator *DefaultPrivValidator
|
||||
if _, err := os.Stat(filePath); err == nil {
|
||||
privValidator = LoadPrivValidator(filePath)
|
||||
} else {
|
||||
@ -97,34 +120,33 @@ func LoadOrGenPrivValidator(filePath string) *PrivValidator {
|
||||
return privValidator
|
||||
}
|
||||
|
||||
func LoadPrivValidator(filePath string) *PrivValidator {
|
||||
func LoadPrivValidator(filePath string) *DefaultPrivValidator {
|
||||
privValJSONBytes, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
Exit(err.Error())
|
||||
}
|
||||
privVal := PrivValidator{}
|
||||
privVal := DefaultPrivValidator{}
|
||||
err = json.Unmarshal(privValJSONBytes, &privVal)
|
||||
if err != nil {
|
||||
Exit(Fmt("Error reading PrivValidator from %v: %v\n", filePath, err))
|
||||
}
|
||||
|
||||
privVal.filePath = filePath
|
||||
privVal.Signer = NewDefaultSigner(privVal.PrivKey)
|
||||
privVal.setPubKeyAndAddress()
|
||||
return &privVal
|
||||
}
|
||||
|
||||
// Generates a new validator with private key.
|
||||
func GenPrivValidator() *PrivValidator {
|
||||
func GenPrivValidator() *DefaultPrivValidator {
|
||||
privKey := crypto.GenPrivKeyEd25519().Wrap()
|
||||
pubKey := privKey.PubKey()
|
||||
return &PrivValidator{
|
||||
Address: pubKey.Address(),
|
||||
PubKey: pubKey,
|
||||
PrivKey: privKey,
|
||||
LastStep: stepNone,
|
||||
filePath: "",
|
||||
return &DefaultPrivValidator{
|
||||
Info: PrivValidatorInfo{
|
||||
Address: pubKey.Address(),
|
||||
PubKey: pubKey,
|
||||
LastStep: stepNone,
|
||||
},
|
||||
Signer: NewDefaultSigner(privKey),
|
||||
filePath: "",
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,40 +154,37 @@ func GenPrivValidator() *PrivValidator {
|
||||
// signer object. Tendermint tracks state in the PrivValidator that might be
|
||||
// saved to disk. Please supply a filepath where Tendermint can save the
|
||||
// private validator.
|
||||
func LoadPrivValidatorWithSigner(signer Signer, filePath string) *PrivValidator {
|
||||
return &PrivValidator{
|
||||
Address: signer.PubKey().Address(),
|
||||
PubKey: signer.PubKey(),
|
||||
LastStep: stepNone,
|
||||
filePath: filePath,
|
||||
func LoadPrivValidatorWithSigner(signer *DefaultSigner, filePath string) *DefaultPrivValidator {
|
||||
return &DefaultPrivValidator{
|
||||
Info: PrivValidatorInfo{
|
||||
Address: signer.PubKey().Address(),
|
||||
PubKey: signer.PubKey(),
|
||||
LastStep: stepNone,
|
||||
},
|
||||
Signer: signer,
|
||||
filePath: filePath,
|
||||
}
|
||||
}
|
||||
|
||||
func (privVal *PrivValidator) SetSigner(s Signer) {
|
||||
privVal.Signer = s
|
||||
privVal.setPubKeyAndAddress()
|
||||
}
|
||||
|
||||
// Overwrite address and pubkey for convenience
|
||||
func (privVal *PrivValidator) setPubKeyAndAddress() {
|
||||
/*func (privVal *DefaultPrivValidator) setPubKeyAndAddress() {
|
||||
privVal.PubKey = privVal.Signer.PubKey()
|
||||
privVal.Address = privVal.PubKey.Address()
|
||||
}
|
||||
}*/
|
||||
|
||||
func (privVal *PrivValidator) SetFile(filePath string) {
|
||||
func (privVal *DefaultPrivValidator) SetFile(filePath string) {
|
||||
privVal.mtx.Lock()
|
||||
defer privVal.mtx.Unlock()
|
||||
privVal.filePath = filePath
|
||||
}
|
||||
|
||||
func (privVal *PrivValidator) Save() {
|
||||
func (privVal *DefaultPrivValidator) Save() {
|
||||
privVal.mtx.Lock()
|
||||
defer privVal.mtx.Unlock()
|
||||
privVal.save()
|
||||
}
|
||||
|
||||
func (privVal *PrivValidator) save() {
|
||||
func (privVal *DefaultPrivValidator) save() {
|
||||
if privVal.filePath == "" {
|
||||
PanicSanity("Cannot save PrivValidator: filePath not set")
|
||||
}
|
||||
@ -182,20 +201,20 @@ func (privVal *PrivValidator) save() {
|
||||
}
|
||||
|
||||
// NOTE: Unsafe!
|
||||
func (privVal *PrivValidator) Reset() {
|
||||
privVal.LastHeight = 0
|
||||
privVal.LastRound = 0
|
||||
privVal.LastStep = 0
|
||||
privVal.LastSignature = crypto.Signature{}
|
||||
privVal.LastSignBytes = nil
|
||||
func (privVal *DefaultPrivValidator) Reset() {
|
||||
privVal.Info.LastHeight = 0
|
||||
privVal.Info.LastRound = 0
|
||||
privVal.Info.LastStep = 0
|
||||
privVal.Info.LastSignature = crypto.Signature{}
|
||||
privVal.Info.LastSignBytes = nil
|
||||
privVal.Save()
|
||||
}
|
||||
|
||||
func (privVal *PrivValidator) GetAddress() []byte {
|
||||
return privVal.Address
|
||||
func (privVal *DefaultPrivValidator) GetAddress() []byte {
|
||||
return privVal.Address()
|
||||
}
|
||||
|
||||
func (privVal *PrivValidator) SignVote(chainID string, vote *Vote) error {
|
||||
func (privVal *DefaultPrivValidator) SignVote(chainID string, vote *Vote) error {
|
||||
privVal.mtx.Lock()
|
||||
defer privVal.mtx.Unlock()
|
||||
signature, err := privVal.signBytesHRS(vote.Height, vote.Round, voteToStep(vote), SignBytes(chainID, vote))
|
||||
@ -206,7 +225,7 @@ func (privVal *PrivValidator) SignVote(chainID string, vote *Vote) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (privVal *PrivValidator) SignProposal(chainID string, proposal *Proposal) error {
|
||||
func (privVal *DefaultPrivValidator) SignProposal(chainID string, proposal *Proposal) error {
|
||||
privVal.mtx.Lock()
|
||||
defer privVal.mtx.Unlock()
|
||||
signature, err := privVal.signBytesHRS(proposal.Height, proposal.Round, stepPropose, SignBytes(chainID, proposal))
|
||||
@ -218,33 +237,34 @@ func (privVal *PrivValidator) SignProposal(chainID string, proposal *Proposal) e
|
||||
}
|
||||
|
||||
// check if there's a regression. Else sign and write the hrs+signature to disk
|
||||
func (privVal *PrivValidator) signBytesHRS(height, round int, step int8, signBytes []byte) (crypto.Signature, error) {
|
||||
func (privVal *DefaultPrivValidator) signBytesHRS(height, round int, step int8, signBytes []byte) (crypto.Signature, error) {
|
||||
sig := crypto.Signature{}
|
||||
info := privVal.Info
|
||||
// If height regression, err
|
||||
if privVal.LastHeight > height {
|
||||
if info.LastHeight > height {
|
||||
return sig, errors.New("Height regression")
|
||||
}
|
||||
// More cases for when the height matches
|
||||
if privVal.LastHeight == height {
|
||||
if info.LastHeight == height {
|
||||
// If round regression, err
|
||||
if privVal.LastRound > round {
|
||||
if info.LastRound > round {
|
||||
return sig, errors.New("Round regression")
|
||||
}
|
||||
// If step regression, err
|
||||
if privVal.LastRound == round {
|
||||
if privVal.LastStep > step {
|
||||
if info.LastRound == round {
|
||||
if info.LastStep > step {
|
||||
return sig, errors.New("Step regression")
|
||||
} else if privVal.LastStep == step {
|
||||
if privVal.LastSignBytes != nil {
|
||||
if privVal.LastSignature.Empty() {
|
||||
} else if info.LastStep == step {
|
||||
if info.LastSignBytes != nil {
|
||||
if info.LastSignature.Empty() {
|
||||
PanicSanity("privVal: LastSignature is nil but LastSignBytes is not!")
|
||||
}
|
||||
// so we dont sign a conflicting vote or proposal
|
||||
// NOTE: proposals are non-deterministic (include time),
|
||||
// so we can actually lose them, but will still never sign conflicting ones
|
||||
if bytes.Equal(privVal.LastSignBytes, signBytes) {
|
||||
// log.Notice("Using privVal.LastSignature", "sig", privVal.LastSignature)
|
||||
return privVal.LastSignature, nil
|
||||
if bytes.Equal(info.LastSignBytes, signBytes) {
|
||||
// log.Notice("Using info.LastSignature", "sig", info.LastSignature)
|
||||
return info.LastSignature, nil
|
||||
}
|
||||
}
|
||||
return sig, errors.New("Step regression")
|
||||
@ -253,45 +273,46 @@ func (privVal *PrivValidator) signBytesHRS(height, round int, step int8, signByt
|
||||
}
|
||||
|
||||
// Sign
|
||||
sig, err := privVal.Sign(signBytes)
|
||||
sig, err := privVal.Signer.Sign(signBytes)
|
||||
if err != nil {
|
||||
return sig, err
|
||||
}
|
||||
|
||||
// Persist height/round/step
|
||||
privVal.LastHeight = height
|
||||
privVal.LastRound = round
|
||||
privVal.LastStep = step
|
||||
privVal.LastSignature = sig
|
||||
privVal.LastSignBytes = signBytes
|
||||
privVal.Info.LastHeight = height
|
||||
privVal.Info.LastRound = round
|
||||
privVal.Info.LastStep = step
|
||||
privVal.Info.LastSignature = sig
|
||||
privVal.Info.LastSignBytes = signBytes
|
||||
privVal.save()
|
||||
|
||||
return sig, nil
|
||||
|
||||
}
|
||||
|
||||
func (privVal *PrivValidator) SignHeartbeat(chainID string, heartbeat *Heartbeat) error {
|
||||
func (privVal *DefaultPrivValidator) SignHeartbeat(chainID string, heartbeat *Heartbeat) error {
|
||||
privVal.mtx.Lock()
|
||||
defer privVal.mtx.Unlock()
|
||||
var err error
|
||||
heartbeat.Signature, err = privVal.Sign(SignBytes(chainID, heartbeat))
|
||||
heartbeat.Signature, err = privVal.Signer.Sign(SignBytes(chainID, heartbeat))
|
||||
return err
|
||||
}
|
||||
|
||||
func (privVal *PrivValidator) String() string {
|
||||
return fmt.Sprintf("PrivValidator{%v LH:%v, LR:%v, LS:%v}", privVal.Address, privVal.LastHeight, privVal.LastRound, privVal.LastStep)
|
||||
func (privVal *DefaultPrivValidator) String() string {
|
||||
info := privVal.Info
|
||||
return fmt.Sprintf("PrivValidator{%v LH:%v, LR:%v, LS:%v}", info.Address, info.LastHeight, info.LastRound, info.LastStep)
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
type PrivValidatorsByAddress []*PrivValidator
|
||||
type PrivValidatorsByAddress []*DefaultPrivValidator
|
||||
|
||||
func (pvs PrivValidatorsByAddress) Len() int {
|
||||
return len(pvs)
|
||||
}
|
||||
|
||||
func (pvs PrivValidatorsByAddress) Less(i, j int) bool {
|
||||
return bytes.Compare(pvs[i].Address, pvs[j].Address) == -1
|
||||
return bytes.Compare(pvs[i].Info.Address, pvs[j].Info.Address) == -1
|
||||
}
|
||||
|
||||
func (pvs PrivValidatorsByAddress) Swap(i, j int) {
|
||||
|
@ -29,29 +29,34 @@ func TestLoadValidator(t *testing.T) {
|
||||
require.Nil(err, "%+v", err)
|
||||
|
||||
serialized := fmt.Sprintf(`{
|
||||
"address": "%s",
|
||||
"pub_key": {
|
||||
"type": "ed25519",
|
||||
"data": "%s"
|
||||
"info": {
|
||||
"address": "%s",
|
||||
"pub_key": {
|
||||
"type": "ed25519",
|
||||
"data": "%s"
|
||||
},
|
||||
"last_height": 0,
|
||||
"last_round": 0,
|
||||
"last_step": 0,
|
||||
"last_signature": null
|
||||
},
|
||||
"priv_key": {
|
||||
"type": "ed25519",
|
||||
"data": "%s"
|
||||
},
|
||||
"last_height": 0,
|
||||
"last_round": 0,
|
||||
"last_step": 0,
|
||||
"last_signature": null
|
||||
"signer": {
|
||||
"priv_key": {
|
||||
"type": "ed25519",
|
||||
"data": "%s"
|
||||
}
|
||||
}
|
||||
}`, addrStr, pubStr, privStr)
|
||||
|
||||
val := PrivValidator{}
|
||||
val := DefaultPrivValidator{}
|
||||
err = json.Unmarshal([]byte(serialized), &val)
|
||||
require.Nil(err, "%+v", err)
|
||||
|
||||
// make sure the values match
|
||||
assert.EqualValues(addrBytes, val.Address)
|
||||
assert.EqualValues(pubKey, val.PubKey)
|
||||
assert.EqualValues(privKey, val.PrivKey)
|
||||
assert.EqualValues(addrBytes, val.Address())
|
||||
assert.EqualValues(pubKey, val.PubKey())
|
||||
valPrivKey := val.Signer.PrivKey
|
||||
assert.EqualValues(privKey, valPrivKey)
|
||||
|
||||
// export it and make sure it is the same
|
||||
out, err := json.Marshal(val)
|
||||
|
@ -30,15 +30,15 @@ func BenchmarkProposalWriteSignBytes(b *testing.B) {
|
||||
func BenchmarkProposalSign(b *testing.B) {
|
||||
privVal := GenPrivValidator()
|
||||
for i := 0; i < b.N; i++ {
|
||||
privVal.Sign(SignBytes("test_chain_id", testProposal))
|
||||
privVal.Signer.Sign(SignBytes("test_chain_id", testProposal))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkProposalVerifySignature(b *testing.B) {
|
||||
signBytes := SignBytes("test_chain_id", testProposal)
|
||||
privVal := GenPrivValidator()
|
||||
signature, _ := privVal.Sign(signBytes)
|
||||
pubKey := privVal.PubKey
|
||||
signature, _ := privVal.Signer.Sign(signBytes)
|
||||
pubKey := privVal.PubKey()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
pubKey.VerifyBytes(SignBytes("test_chain_id", testProposal), signature)
|
||||
|
@ -106,7 +106,7 @@ func (vc validatorCodec) Compare(o1 interface{}, o2 interface{}) int {
|
||||
//--------------------------------------------------------------------------------
|
||||
// For testing...
|
||||
|
||||
func RandValidator(randPower bool, minPower int64) (*Validator, *PrivValidator) {
|
||||
func RandValidator(randPower bool, minPower int64) (*Validator, *DefaultPrivValidator) {
|
||||
privVal := GenPrivValidator()
|
||||
_, tempFilePath := cmn.Tempfile("priv_validator_")
|
||||
privVal.SetFile(tempFilePath)
|
||||
@ -114,6 +114,6 @@ func RandValidator(randPower bool, minPower int64) (*Validator, *PrivValidator)
|
||||
if randPower {
|
||||
votePower += int64(cmn.RandUint32())
|
||||
}
|
||||
val := NewValidator(privVal.PubKey, votePower)
|
||||
val := NewValidator(privVal.PubKey(), votePower)
|
||||
return val, privVal
|
||||
}
|
||||
|
@ -369,9 +369,9 @@ func (ac accumComparable) Less(o interface{}) bool {
|
||||
// For testing
|
||||
|
||||
// NOTE: PrivValidator are in order.
|
||||
func RandValidatorSet(numValidators int, votingPower int64) (*ValidatorSet, []*PrivValidator) {
|
||||
func RandValidatorSet(numValidators int, votingPower int64) (*ValidatorSet, []*DefaultPrivValidator) {
|
||||
vals := make([]*Validator, numValidators)
|
||||
privValidators := make([]*PrivValidator, numValidators)
|
||||
privValidators := make([]*DefaultPrivValidator, numValidators)
|
||||
for i := 0; i < numValidators; i++ {
|
||||
val, privValidator := RandValidator(false, votingPower)
|
||||
vals[i] = val
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
// NOTE: privValidators are in order
|
||||
func randVoteSet(height int, round int, type_ byte, numValidators int, votingPower int64) (*VoteSet, *ValidatorSet, []*PrivValidator) {
|
||||
func randVoteSet(height int, round int, type_ byte, numValidators int, votingPower int64) (*VoteSet, *ValidatorSet, []*DefaultPrivValidator) {
|
||||
valSet, privValidators := RandValidatorSet(numValidators, votingPower)
|
||||
return NewVoteSet("test_chain_id", height, round, type_, valSet), valSet, privValidators
|
||||
}
|
||||
@ -59,9 +59,9 @@ func withBlockPartsHeader(vote *Vote, blockPartsHeader PartSetHeader) *Vote {
|
||||
return vote
|
||||
}
|
||||
|
||||
func signAddVote(privVal *PrivValidator, vote *Vote, voteSet *VoteSet) (bool, error) {
|
||||
func signAddVote(privVal *DefaultPrivValidator, vote *Vote, voteSet *VoteSet) (bool, error) {
|
||||
var err error
|
||||
vote.Signature, err = privVal.Sign(SignBytes(voteSet.ChainID(), vote))
|
||||
vote.Signature, err = privVal.Signer.Sign(SignBytes(voteSet.ChainID(), vote))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -76,7 +76,7 @@ func TestAddVote(t *testing.T) {
|
||||
|
||||
// t.Logf(">> %v", voteSet)
|
||||
|
||||
if voteSet.GetByAddress(val0.Address) != nil {
|
||||
if voteSet.GetByAddress(val0.Address()) != nil {
|
||||
t.Errorf("Expected GetByAddress(val0.Address) to be nil")
|
||||
}
|
||||
if voteSet.BitArray().GetIndex(0) {
|
||||
@ -88,7 +88,7 @@ func TestAddVote(t *testing.T) {
|
||||
}
|
||||
|
||||
vote := &Vote{
|
||||
ValidatorAddress: val0.Address,
|
||||
ValidatorAddress: val0.Address(),
|
||||
ValidatorIndex: 0, // since privValidators are in order
|
||||
Height: height,
|
||||
Round: round,
|
||||
@ -100,7 +100,7 @@ func TestAddVote(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if voteSet.GetByAddress(val0.Address) == nil {
|
||||
if voteSet.GetByAddress(val0.Address()) == nil {
|
||||
t.Errorf("Expected GetByAddress(val0.Address) to be present")
|
||||
}
|
||||
if !voteSet.BitArray().GetIndex(0) {
|
||||
@ -126,7 +126,7 @@ func Test2_3Majority(t *testing.T) {
|
||||
}
|
||||
// 6 out of 10 voted for nil.
|
||||
for i := 0; i < 6; i++ {
|
||||
vote := withValidator(voteProto, privValidators[i].Address, i)
|
||||
vote := withValidator(voteProto, privValidators[i].Address(), i)
|
||||
signAddVote(privValidators[i], vote, voteSet)
|
||||
}
|
||||
blockID, ok := voteSet.TwoThirdsMajority()
|
||||
@ -136,7 +136,7 @@ func Test2_3Majority(t *testing.T) {
|
||||
|
||||
// 7th validator voted for some blockhash
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[6].Address, 6)
|
||||
vote := withValidator(voteProto, privValidators[6].Address(), 6)
|
||||
signAddVote(privValidators[6], withBlockHash(vote, RandBytes(32)), voteSet)
|
||||
blockID, ok = voteSet.TwoThirdsMajority()
|
||||
if ok || !blockID.IsZero() {
|
||||
@ -146,7 +146,7 @@ func Test2_3Majority(t *testing.T) {
|
||||
|
||||
// 8th validator voted for nil.
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[7].Address, 7)
|
||||
vote := withValidator(voteProto, privValidators[7].Address(), 7)
|
||||
signAddVote(privValidators[7], vote, voteSet)
|
||||
blockID, ok = voteSet.TwoThirdsMajority()
|
||||
if !ok || !blockID.IsZero() {
|
||||
@ -174,7 +174,7 @@ func Test2_3MajorityRedux(t *testing.T) {
|
||||
|
||||
// 66 out of 100 voted for nil.
|
||||
for i := 0; i < 66; i++ {
|
||||
vote := withValidator(voteProto, privValidators[i].Address, i)
|
||||
vote := withValidator(voteProto, privValidators[i].Address(), i)
|
||||
signAddVote(privValidators[i], vote, voteSet)
|
||||
}
|
||||
blockID, ok := voteSet.TwoThirdsMajority()
|
||||
@ -184,7 +184,7 @@ func Test2_3MajorityRedux(t *testing.T) {
|
||||
|
||||
// 67th validator voted for nil
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[66].Address, 66)
|
||||
vote := withValidator(voteProto, privValidators[66].Address(), 66)
|
||||
signAddVote(privValidators[66], withBlockHash(vote, nil), voteSet)
|
||||
blockID, ok = voteSet.TwoThirdsMajority()
|
||||
if ok || !blockID.IsZero() {
|
||||
@ -194,7 +194,7 @@ func Test2_3MajorityRedux(t *testing.T) {
|
||||
|
||||
// 68th validator voted for a different BlockParts PartSetHeader
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[67].Address, 67)
|
||||
vote := withValidator(voteProto, privValidators[67].Address(), 67)
|
||||
blockPartsHeader := PartSetHeader{blockPartsTotal, crypto.CRandBytes(32)}
|
||||
signAddVote(privValidators[67], withBlockPartsHeader(vote, blockPartsHeader), voteSet)
|
||||
blockID, ok = voteSet.TwoThirdsMajority()
|
||||
@ -205,7 +205,7 @@ func Test2_3MajorityRedux(t *testing.T) {
|
||||
|
||||
// 69th validator voted for different BlockParts Total
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[68].Address, 68)
|
||||
vote := withValidator(voteProto, privValidators[68].Address(), 68)
|
||||
blockPartsHeader := PartSetHeader{blockPartsTotal + 1, blockPartsHeader.Hash}
|
||||
signAddVote(privValidators[68], withBlockPartsHeader(vote, blockPartsHeader), voteSet)
|
||||
blockID, ok = voteSet.TwoThirdsMajority()
|
||||
@ -216,7 +216,7 @@ func Test2_3MajorityRedux(t *testing.T) {
|
||||
|
||||
// 70th validator voted for different BlockHash
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[69].Address, 69)
|
||||
vote := withValidator(voteProto, privValidators[69].Address(), 69)
|
||||
signAddVote(privValidators[69], withBlockHash(vote, RandBytes(32)), voteSet)
|
||||
blockID, ok = voteSet.TwoThirdsMajority()
|
||||
if ok || !blockID.IsZero() {
|
||||
@ -226,7 +226,7 @@ func Test2_3MajorityRedux(t *testing.T) {
|
||||
|
||||
// 71st validator voted for the right BlockHash & BlockPartsHeader
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[70].Address, 70)
|
||||
vote := withValidator(voteProto, privValidators[70].Address(), 70)
|
||||
signAddVote(privValidators[70], vote, voteSet)
|
||||
blockID, ok = voteSet.TwoThirdsMajority()
|
||||
if !ok || !blockID.Equals(BlockID{blockHash, blockPartsHeader}) {
|
||||
@ -250,7 +250,7 @@ func TestBadVotes(t *testing.T) {
|
||||
|
||||
// val0 votes for nil.
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[0].Address, 0)
|
||||
vote := withValidator(voteProto, privValidators[0].Address(), 0)
|
||||
added, err := signAddVote(privValidators[0], vote, voteSet)
|
||||
if !added || err != nil {
|
||||
t.Errorf("Expected VoteSet.Add to succeed")
|
||||
@ -259,7 +259,7 @@ func TestBadVotes(t *testing.T) {
|
||||
|
||||
// val0 votes again for some block.
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[0].Address, 0)
|
||||
vote := withValidator(voteProto, privValidators[0].Address(), 0)
|
||||
added, err := signAddVote(privValidators[0], withBlockHash(vote, RandBytes(32)), voteSet)
|
||||
if added || err == nil {
|
||||
t.Errorf("Expected VoteSet.Add to fail, conflicting vote.")
|
||||
@ -268,7 +268,7 @@ func TestBadVotes(t *testing.T) {
|
||||
|
||||
// val1 votes on another height
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[1].Address, 1)
|
||||
vote := withValidator(voteProto, privValidators[1].Address(), 1)
|
||||
added, err := signAddVote(privValidators[1], withHeight(vote, height+1), voteSet)
|
||||
if added || err == nil {
|
||||
t.Errorf("Expected VoteSet.Add to fail, wrong height")
|
||||
@ -277,7 +277,7 @@ func TestBadVotes(t *testing.T) {
|
||||
|
||||
// val2 votes on another round
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[2].Address, 2)
|
||||
vote := withValidator(voteProto, privValidators[2].Address(), 2)
|
||||
added, err := signAddVote(privValidators[2], withRound(vote, round+1), voteSet)
|
||||
if added || err == nil {
|
||||
t.Errorf("Expected VoteSet.Add to fail, wrong round")
|
||||
@ -286,7 +286,7 @@ func TestBadVotes(t *testing.T) {
|
||||
|
||||
// val3 votes of another type.
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[3].Address, 3)
|
||||
vote := withValidator(voteProto, privValidators[3].Address(), 3)
|
||||
added, err := signAddVote(privValidators[3], withType(vote, VoteTypePrecommit), voteSet)
|
||||
if added || err == nil {
|
||||
t.Errorf("Expected VoteSet.Add to fail, wrong type")
|
||||
@ -311,7 +311,7 @@ func TestConflicts(t *testing.T) {
|
||||
|
||||
// val0 votes for nil.
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[0].Address, 0)
|
||||
vote := withValidator(voteProto, privValidators[0].Address(), 0)
|
||||
added, err := signAddVote(privValidators[0], vote, voteSet)
|
||||
if !added || err != nil {
|
||||
t.Errorf("Expected VoteSet.Add to succeed")
|
||||
@ -320,7 +320,7 @@ func TestConflicts(t *testing.T) {
|
||||
|
||||
// val0 votes again for blockHash1.
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[0].Address, 0)
|
||||
vote := withValidator(voteProto, privValidators[0].Address(), 0)
|
||||
added, err := signAddVote(privValidators[0], withBlockHash(vote, blockHash1), voteSet)
|
||||
if added {
|
||||
t.Errorf("Expected VoteSet.Add to fail, conflicting vote.")
|
||||
@ -335,7 +335,7 @@ func TestConflicts(t *testing.T) {
|
||||
|
||||
// val0 votes again for blockHash1.
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[0].Address, 0)
|
||||
vote := withValidator(voteProto, privValidators[0].Address(), 0)
|
||||
added, err := signAddVote(privValidators[0], withBlockHash(vote, blockHash1), voteSet)
|
||||
if !added {
|
||||
t.Errorf("Expected VoteSet.Add to succeed, called SetPeerMaj23().")
|
||||
@ -350,7 +350,7 @@ func TestConflicts(t *testing.T) {
|
||||
|
||||
// val0 votes again for blockHash1.
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[0].Address, 0)
|
||||
vote := withValidator(voteProto, privValidators[0].Address(), 0)
|
||||
added, err := signAddVote(privValidators[0], withBlockHash(vote, blockHash2), voteSet)
|
||||
if added {
|
||||
t.Errorf("Expected VoteSet.Add to fail, duplicate SetPeerMaj23() from peerA")
|
||||
@ -362,7 +362,7 @@ func TestConflicts(t *testing.T) {
|
||||
|
||||
// val1 votes for blockHash1.
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[1].Address, 1)
|
||||
vote := withValidator(voteProto, privValidators[1].Address(), 1)
|
||||
added, err := signAddVote(privValidators[1], withBlockHash(vote, blockHash1), voteSet)
|
||||
if !added || err != nil {
|
||||
t.Errorf("Expected VoteSet.Add to succeed")
|
||||
@ -379,7 +379,7 @@ func TestConflicts(t *testing.T) {
|
||||
|
||||
// val2 votes for blockHash2.
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[2].Address, 2)
|
||||
vote := withValidator(voteProto, privValidators[2].Address(), 2)
|
||||
added, err := signAddVote(privValidators[2], withBlockHash(vote, blockHash2), voteSet)
|
||||
if !added || err != nil {
|
||||
t.Errorf("Expected VoteSet.Add to succeed")
|
||||
@ -399,7 +399,7 @@ func TestConflicts(t *testing.T) {
|
||||
|
||||
// val2 votes for blockHash1.
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[2].Address, 2)
|
||||
vote := withValidator(voteProto, privValidators[2].Address(), 2)
|
||||
added, err := signAddVote(privValidators[2], withBlockHash(vote, blockHash1), voteSet)
|
||||
if !added {
|
||||
t.Errorf("Expected VoteSet.Add to succeed")
|
||||
@ -439,7 +439,7 @@ func TestMakeCommit(t *testing.T) {
|
||||
|
||||
// 6 out of 10 voted for some block.
|
||||
for i := 0; i < 6; i++ {
|
||||
vote := withValidator(voteProto, privValidators[i].Address, i)
|
||||
vote := withValidator(voteProto, privValidators[i].Address(), i)
|
||||
signAddVote(privValidators[i], vote, voteSet)
|
||||
}
|
||||
|
||||
@ -448,7 +448,7 @@ func TestMakeCommit(t *testing.T) {
|
||||
|
||||
// 7th voted for some other block.
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[6].Address, 6)
|
||||
vote := withValidator(voteProto, privValidators[6].Address(), 6)
|
||||
vote = withBlockHash(vote, RandBytes(32))
|
||||
vote = withBlockPartsHeader(vote, PartSetHeader{123, RandBytes(32)})
|
||||
signAddVote(privValidators[6], vote, voteSet)
|
||||
@ -456,7 +456,7 @@ func TestMakeCommit(t *testing.T) {
|
||||
|
||||
// The 8th voted like everyone else.
|
||||
{
|
||||
vote := withValidator(voteProto, privValidators[7].Address, 7)
|
||||
vote := withValidator(voteProto, privValidators[7].Address(), 7)
|
||||
signAddVote(privValidators[7], vote, voteSet)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user