mirror of
https://github.com/fluencelabs/tendermint
synced 2025-07-03 06:31:40 +00:00
consensus cleanup, privValidator config
This commit is contained in:
@ -9,12 +9,12 @@ import (
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
type PrivValidator struct {
|
||||
state.PrivAccount
|
||||
db db_.DB
|
||||
state.PrivAccount
|
||||
}
|
||||
|
||||
func NewPrivValidator(priv *state.PrivAccount, db db_.DB) *PrivValidator {
|
||||
return &PrivValidator{*priv, db}
|
||||
func NewPrivValidator(db db_.DB, priv *state.PrivAccount) *PrivValidator {
|
||||
return &PrivValidator{db, *priv}
|
||||
}
|
||||
|
||||
// Double signing results in a panic.
|
||||
|
@ -58,14 +58,14 @@ func calcRound(startTime time.Time) uint16 {
|
||||
if now.Before(startTime) {
|
||||
return 0
|
||||
}
|
||||
// Start + D_0 * R + D_delta * (R^2 - R)/2 <= Now; find largest integer R.
|
||||
// D_delta * R^2 + (2D_0 - D_delta) * R + 2(Start - Now) <= 0.
|
||||
// Start + D_0 * R + D_delta * (R^2 - R)/2 <= Now; find largest integer R.
|
||||
// D_delta * R^2 + (2D_0 - D_delta) * R + 2(Start - Now) <= 0.
|
||||
// AR^2 + BR + C <= 0; A = D_delta, B = (2_D0 - D_delta), C = 2(Start - Now).
|
||||
// R = Floor((-B + Sqrt(B^2 - 4AC))/2A)
|
||||
A := float64(roundDurationDelta)
|
||||
B := 2.0*float64(roundDuration0) - float64(roundDurationDelta)
|
||||
C := 2.0 * float64(startTime.Sub(now))
|
||||
R := math.Floor((-B + math.Sqrt(B*B-4.0*A*C)/(2*A)))
|
||||
R := math.Floor((-B + math.Sqrt(B*B-4.0*A*C)) / (2 * A))
|
||||
if math.IsNaN(R) {
|
||||
panic("Could not calc round, should not happen")
|
||||
}
|
||||
@ -300,20 +300,20 @@ func (conR *ConsensusReactor) stepTransitionRoutine() {
|
||||
// It's a new RoundState.
|
||||
if elapsedRatio < 0 {
|
||||
// startTime is in the future.
|
||||
time.Sleep(time.Duration(-1.0*elapsedRatio) * roundDuration)
|
||||
time.Sleep(time.Duration((-1.0 * elapsedRatio) * float64(roundDuration)))
|
||||
}
|
||||
conR.doActionCh <- RoundAction{rs.Height, rs.Round, RoundActionPropose}
|
||||
case RoundStepPropose:
|
||||
// Wake up when it's time to vote.
|
||||
time.Sleep(time.Duration(roundDeadlinePrevote-elapsedRatio) * roundDuration)
|
||||
time.Sleep(time.Duration((roundDeadlinePrevote - elapsedRatio) * float64(roundDuration)))
|
||||
conR.doActionCh <- RoundAction{rs.Height, rs.Round, RoundActionPrevote}
|
||||
case RoundStepPrevote:
|
||||
// Wake up when it's time to precommit.
|
||||
time.Sleep(time.Duration(roundDeadlinePrecommit-elapsedRatio) * roundDuration)
|
||||
time.Sleep(time.Duration((roundDeadlinePrecommit - elapsedRatio) * float64(roundDuration)))
|
||||
conR.doActionCh <- RoundAction{rs.Height, rs.Round, RoundActionPrecommit}
|
||||
case RoundStepPrecommit:
|
||||
// Wake up when the round is over.
|
||||
time.Sleep(time.Duration(1.0-elapsedRatio) * roundDuration)
|
||||
time.Sleep(time.Duration((1.0 - elapsedRatio) * float64(roundDuration)))
|
||||
conR.doActionCh <- RoundAction{rs.Height, rs.Round, RoundActionNextRound}
|
||||
case RoundStepCommit:
|
||||
panic("Should not happen: RoundStepCommit waits until +2/3 commits.")
|
||||
@ -344,6 +344,8 @@ ACTION_LOOP:
|
||||
round := roundAction.Round
|
||||
action := roundAction.Action
|
||||
rs := conR.conS.GetRoundState()
|
||||
log.Info("Running round action A:%X %v", action, rs.Description())
|
||||
|
||||
broadcastNewRoundStep := func(step RoundStep) {
|
||||
// Broadcast NewRoundStepMessage
|
||||
msg := &NewRoundStepMessage{
|
||||
@ -379,14 +381,11 @@ ACTION_LOOP:
|
||||
if rs.Step >= RoundStepPrevote {
|
||||
continue ACTION_LOOP
|
||||
}
|
||||
hash := conR.conS.RunActionPrevote(rs.Height, rs.Round)
|
||||
vote := conR.conS.RunActionPrevote(rs.Height, rs.Round)
|
||||
broadcastNewRoundStep(RoundStepPrevote)
|
||||
conR.signAndBroadcastVote(rs, &Vote{
|
||||
Height: rs.Height,
|
||||
Round: rs.Round,
|
||||
Type: VoteTypePrevote,
|
||||
BlockHash: hash,
|
||||
})
|
||||
if vote != nil {
|
||||
conR.broadcastVote(vote)
|
||||
}
|
||||
scheduleNextAction()
|
||||
continue ACTION_LOOP
|
||||
|
||||
@ -394,15 +393,10 @@ ACTION_LOOP:
|
||||
if rs.Step >= RoundStepPrecommit {
|
||||
continue ACTION_LOOP
|
||||
}
|
||||
hash := conR.conS.RunActionPrecommit(rs.Height, rs.Round)
|
||||
vote := conR.conS.RunActionPrecommit(rs.Height, rs.Round)
|
||||
broadcastNewRoundStep(RoundStepPrecommit)
|
||||
if len(hash) > 0 {
|
||||
conR.signAndBroadcastVote(rs, &Vote{
|
||||
Height: rs.Height,
|
||||
Round: rs.Round,
|
||||
Type: VoteTypePrecommit,
|
||||
BlockHash: hash,
|
||||
})
|
||||
if vote != nil {
|
||||
conR.broadcastVote(vote)
|
||||
}
|
||||
scheduleNextAction()
|
||||
continue ACTION_LOOP
|
||||
@ -420,17 +414,10 @@ ACTION_LOOP:
|
||||
continue ACTION_LOOP
|
||||
}
|
||||
// NOTE: Duplicated in RoundActionCommitWait.
|
||||
hash := conR.conS.RunActionCommit(rs.Height)
|
||||
if len(hash) > 0 {
|
||||
broadcastNewRoundStep(RoundStepCommit)
|
||||
conR.signAndBroadcastVote(rs, &Vote{
|
||||
Height: rs.Height,
|
||||
Round: rs.Round,
|
||||
Type: VoteTypeCommit,
|
||||
BlockHash: hash,
|
||||
})
|
||||
} else {
|
||||
panic("This shouldn't happen")
|
||||
vote := conR.conS.RunActionCommit(rs.Height, rs.Round)
|
||||
broadcastNewRoundStep(RoundStepCommit)
|
||||
if vote != nil {
|
||||
conR.broadcastVote(vote)
|
||||
}
|
||||
// do not schedule next action.
|
||||
continue ACTION_LOOP
|
||||
@ -442,21 +429,14 @@ ACTION_LOOP:
|
||||
// Commit first we haven't already.
|
||||
if rs.Step < RoundStepCommit {
|
||||
// NOTE: Duplicated in RoundActionCommit.
|
||||
hash := conR.conS.RunActionCommit(rs.Height)
|
||||
if len(hash) > 0 {
|
||||
broadcastNewRoundStep(RoundStepCommit)
|
||||
conR.signAndBroadcastVote(rs, &Vote{
|
||||
Height: rs.Height,
|
||||
Round: rs.Round,
|
||||
Type: VoteTypeCommit,
|
||||
BlockHash: hash,
|
||||
})
|
||||
} else {
|
||||
panic("This shouldn't happen")
|
||||
vote := conR.conS.RunActionCommit(rs.Height, rs.Round)
|
||||
broadcastNewRoundStep(RoundStepCommit)
|
||||
if vote != nil {
|
||||
conR.broadcastVote(vote)
|
||||
}
|
||||
}
|
||||
// Wait for more commit votes.
|
||||
conR.conS.RunActionCommitWait(rs.Height)
|
||||
conR.conS.RunActionCommitWait(rs.Height, rs.Round)
|
||||
scheduleNextAction()
|
||||
continue ACTION_LOOP
|
||||
|
||||
@ -464,7 +444,7 @@ ACTION_LOOP:
|
||||
if rs.Step != RoundStepCommitWait {
|
||||
panic("This shouldn't happen")
|
||||
}
|
||||
conR.conS.RunActionFinalize(rs.Height)
|
||||
conR.conS.RunActionFinalize(rs.Height, rs.Round)
|
||||
// Height has been incremented, step is now RoundStepStart.
|
||||
scheduleNextAction()
|
||||
continue ACTION_LOOP
|
||||
@ -478,13 +458,9 @@ ACTION_LOOP:
|
||||
}
|
||||
}
|
||||
|
||||
func (conR *ConsensusReactor) signAndBroadcastVote(rs *RoundState, vote *Vote) {
|
||||
if rs.PrivValidator != nil {
|
||||
rs.PrivValidator.Sign(vote)
|
||||
conR.conS.AddVote(vote)
|
||||
msg := p2p.TypedMessage{msgTypeVote, vote}
|
||||
conR.sw.Broadcast(VoteCh, msg)
|
||||
}
|
||||
func (conR *ConsensusReactor) broadcastVote(vote *Vote) {
|
||||
msg := p2p.TypedMessage{msgTypeVote, vote}
|
||||
conR.sw.Broadcast(VoteCh, msg)
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
@ -826,7 +802,7 @@ func (m *NewRoundStepMessage) WriteTo(w io.Writer) (n int64, err error) {
|
||||
}
|
||||
|
||||
func (m *NewRoundStepMessage) String() string {
|
||||
return fmt.Sprintf("[NewRoundStepMessage H:%v R:%v]", m.Height, m.Round)
|
||||
return fmt.Sprintf("[NewRoundStep %v/%v/%X]", m.Height, m.Round, m.Step)
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
@ -22,8 +22,8 @@ const (
|
||||
RoundStepPropose = RoundStep(0x01) // Did propose, gossip proposal.
|
||||
RoundStepPrevote = RoundStep(0x02) // Did prevote, gossip prevotes.
|
||||
RoundStepPrecommit = RoundStep(0x03) // Did precommit, gossip precommits.
|
||||
RoundStepCommit = RoundStep(0x04) // Did commit, gossip commits.
|
||||
RoundStepCommitWait = RoundStep(0x05) // Found +2/3 commits, wait more.
|
||||
RoundStepCommit = RoundStep(0x10) // Did commit, gossip commits.
|
||||
RoundStepCommitWait = RoundStep(0x11) // Found +2/3 commits, wait more.
|
||||
|
||||
// If a block could not be committed at a given round,
|
||||
// we progress to the next round, skipping RoundStepCommit.
|
||||
@ -37,9 +37,9 @@ const (
|
||||
RoundActionPrevote = RoundActionType(0x01) // Goto RoundStepPrevote
|
||||
RoundActionPrecommit = RoundActionType(0x02) // Goto RoundStepPrecommit
|
||||
RoundActionNextRound = RoundActionType(0x04) // Goto next round RoundStepStart
|
||||
RoundActionCommit = RoundActionType(0x05) // Goto RoundStepCommit or RoundStepStart next round
|
||||
RoundActionCommitWait = RoundActionType(0x06) // Goto RoundStepCommitWait
|
||||
RoundActionFinalize = RoundActionType(0x07) // Goto RoundStepStart next height
|
||||
RoundActionCommit = RoundActionType(0x10) // Goto RoundStepCommit or RoundStepStart next round
|
||||
RoundActionCommitWait = RoundActionType(0x11) // Goto RoundStepCommitWait
|
||||
RoundActionFinalize = RoundActionType(0x12) // Goto RoundStepStart next height
|
||||
)
|
||||
|
||||
var (
|
||||
@ -107,10 +107,15 @@ func (rs *RoundState) StringWithIndent(indent string) string {
|
||||
indent, rs.Prevotes.StringWithIndent(indent+" "),
|
||||
indent, rs.Precommits.StringWithIndent(indent+" "),
|
||||
indent, rs.Commits.StringWithIndent(indent+" "),
|
||||
indent, rs.LastCommits.StringWithIndent(indent+" "),
|
||||
indent, rs.LastCommits.Description(),
|
||||
indent)
|
||||
}
|
||||
|
||||
func (rs *RoundState) Description() string {
|
||||
return fmt.Sprintf(`RS{%v/%v/%X %v}`,
|
||||
rs.Height, rs.Round, rs.Step, rs.StartTime)
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
// Tracks consensus state across block heights and rounds.
|
||||
@ -298,17 +303,21 @@ func (cs *ConsensusState) RunActionPropose(height uint32, round uint16) {
|
||||
cs.ProposalPOLPartSet = polPartSet
|
||||
}
|
||||
|
||||
func (cs *ConsensusState) RunActionPrevote(height uint32, round uint16) []byte {
|
||||
func (cs *ConsensusState) RunActionPrevote(height uint32, round uint16) *Vote {
|
||||
cs.mtx.Lock()
|
||||
defer cs.mtx.Unlock()
|
||||
if cs.Height != height || cs.Round != round {
|
||||
return nil
|
||||
Panicf("RunActionPrevote(%v/%v), expected %v/%v", height, round, cs.Height, cs.Round)
|
||||
}
|
||||
cs.Step = RoundStepPrevote
|
||||
|
||||
// If a block is locked, prevote that.
|
||||
if cs.LockedBlock != nil {
|
||||
return cs.LockedBlock.Hash()
|
||||
return cs.signAddVote(VoteTypePrevote, cs.LockedBlock.Hash())
|
||||
}
|
||||
// If ProposalBlock is nil, prevote nil.
|
||||
if cs.ProposalBlock == nil {
|
||||
return nil
|
||||
}
|
||||
// Try staging proposed block.
|
||||
err := cs.stageBlock(cs.ProposalBlock)
|
||||
@ -317,18 +326,18 @@ func (cs *ConsensusState) RunActionPrevote(height uint32, round uint16) []byte {
|
||||
return nil
|
||||
} else {
|
||||
// Prevote block.
|
||||
return cs.ProposalBlock.Hash()
|
||||
return cs.signAddVote(VoteTypePrevote, cs.ProposalBlock.Hash())
|
||||
}
|
||||
}
|
||||
|
||||
// Lock the ProposalBlock if we have enough prevotes for it,
|
||||
// or unlock an existing lock if +2/3 of prevotes were nil.
|
||||
// Returns a blockhash if a block was locked.
|
||||
func (cs *ConsensusState) RunActionPrecommit(height uint32, round uint16) []byte {
|
||||
func (cs *ConsensusState) RunActionPrecommit(height uint32, round uint16) *Vote {
|
||||
cs.mtx.Lock()
|
||||
defer cs.mtx.Unlock()
|
||||
if cs.Height != height || cs.Round != round {
|
||||
return nil
|
||||
Panicf("RunActionPrecommit(%v/%v), expected %v/%v", height, round, cs.Height, cs.Round)
|
||||
}
|
||||
cs.Step = RoundStepPrecommit
|
||||
|
||||
@ -352,10 +361,10 @@ func (cs *ConsensusState) RunActionPrecommit(height uint32, round uint16) []byte
|
||||
}
|
||||
cs.LockedBlock = cs.ProposalBlock
|
||||
cs.LockedBlockPartSet = cs.ProposalBlockPartSet
|
||||
return hash
|
||||
return cs.signAddVote(VoteTypePrecommit, hash)
|
||||
} else if cs.LockedBlock.HashesTo(hash) {
|
||||
// +2/3 prevoted for already locked block
|
||||
return hash
|
||||
return cs.signAddVote(VoteTypePrecommit, hash)
|
||||
} else {
|
||||
// We don't have the block that hashes to hash.
|
||||
// Unlock if we're locked.
|
||||
@ -373,11 +382,11 @@ func (cs *ConsensusState) RunActionPrecommit(height uint32, round uint16) []byte
|
||||
// and returns the committed block.
|
||||
// Commit is not finalized until FinalizeCommit() is called.
|
||||
// This allows us to stay at this height and gather more commits.
|
||||
func (cs *ConsensusState) RunActionCommit(height uint32) []byte {
|
||||
func (cs *ConsensusState) RunActionCommit(height uint32, round uint16) *Vote {
|
||||
cs.mtx.Lock()
|
||||
defer cs.mtx.Unlock()
|
||||
if cs.Height != height {
|
||||
return nil
|
||||
if cs.Height != height || cs.Round != round {
|
||||
Panicf("RunActionCommit(%v/%v), expected %v/%v", height, round, cs.Height, cs.Round)
|
||||
}
|
||||
cs.Step = RoundStepCommit
|
||||
|
||||
@ -424,17 +433,17 @@ func (cs *ConsensusState) RunActionCommit(height uint32) []byte {
|
||||
// Update mempool.
|
||||
cs.mempool.ResetForBlockAndState(block, cs.stagedState)
|
||||
|
||||
return block.Hash()
|
||||
return cs.signAddVote(VoteTypeCommit, block.Hash())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs *ConsensusState) RunActionCommitWait(height uint32) {
|
||||
func (cs *ConsensusState) RunActionCommitWait(height uint32, round uint16) {
|
||||
cs.mtx.Lock()
|
||||
defer cs.mtx.Unlock()
|
||||
if cs.Height != height {
|
||||
return
|
||||
if cs.Height != height || cs.Round != round {
|
||||
Panicf("RunActionCommitWait(%v/%v), expected %v/%v", height, round, cs.Height, cs.Round)
|
||||
}
|
||||
cs.Step = RoundStepCommitWait
|
||||
|
||||
@ -445,11 +454,11 @@ func (cs *ConsensusState) RunActionCommitWait(height uint32) {
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *ConsensusState) RunActionFinalize(height uint32) {
|
||||
func (cs *ConsensusState) RunActionFinalize(height uint32, round uint16) {
|
||||
cs.mtx.Lock()
|
||||
defer cs.mtx.Unlock()
|
||||
if cs.Height != height {
|
||||
return
|
||||
if cs.Height != height || cs.Round != round {
|
||||
Panicf("RunActionFinalize(%v/%v), expected %v/%v", height, round, cs.Height, cs.Round)
|
||||
}
|
||||
|
||||
// What was staged becomes committed.
|
||||
@ -557,6 +566,9 @@ func (cs *ConsensusState) AddVote(vote *Vote) (added bool, err error) {
|
||||
}
|
||||
|
||||
func (cs *ConsensusState) stageBlock(block *Block) error {
|
||||
if block == nil {
|
||||
panic("Cannot stage nil block")
|
||||
}
|
||||
|
||||
// Already staged?
|
||||
if cs.stagedBlock == block {
|
||||
@ -577,3 +589,18 @@ func (cs *ConsensusState) stageBlock(block *Block) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *ConsensusState) signAddVote(type_ byte, hash []byte) *Vote {
|
||||
if cs.PrivValidator == nil || !cs.Validators.HasId(cs.PrivValidator.Id) {
|
||||
return nil
|
||||
}
|
||||
vote := &Vote{
|
||||
Height: cs.Height,
|
||||
Round: cs.Round,
|
||||
Type: type_,
|
||||
BlockHash: hash,
|
||||
}
|
||||
cs.PrivValidator.Sign(vote)
|
||||
cs.AddVote(vote)
|
||||
return vote
|
||||
}
|
||||
|
@ -50,6 +50,15 @@ func makeConsensusState() (*ConsensusState, []*state.PrivAccount) {
|
||||
return cs, privAccounts
|
||||
}
|
||||
|
||||
func assertPanics(t *testing.T, msg string, f func()) {
|
||||
defer func() {
|
||||
if err := recover(); err == nil {
|
||||
t.Error("Should have panic'd, but didn't. %v", msg)
|
||||
}
|
||||
}()
|
||||
f()
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
func TestSetupRound(t *testing.T) {
|
||||
@ -91,14 +100,9 @@ func TestSetupRound(t *testing.T) {
|
||||
}
|
||||
|
||||
// Setup round 1 (should fail)
|
||||
{
|
||||
defer func() {
|
||||
if e := recover(); e == nil {
|
||||
t.Errorf("Expected to panic, round did not increment")
|
||||
}
|
||||
}()
|
||||
assertPanics(t, "Round did not increment", func() {
|
||||
cs.SetupRound(1)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@ -113,7 +117,7 @@ func TestRunActionProposeNoPrivValidator(t *testing.T) {
|
||||
|
||||
func TestRunActionPropose(t *testing.T) {
|
||||
cs, privAccounts := makeConsensusState()
|
||||
priv := NewPrivValidator(privAccounts[0], db_.NewMemDB())
|
||||
priv := NewPrivValidator(db_.NewMemDB(), privAccounts[0])
|
||||
cs.SetPrivValidator(priv)
|
||||
|
||||
cs.RunActionPropose(1, 0)
|
||||
@ -147,28 +151,22 @@ func checkRoundState(t *testing.T, cs *ConsensusState,
|
||||
|
||||
func TestRunActionPrecommitCommitFinalize(t *testing.T) {
|
||||
cs, privAccounts := makeConsensusState()
|
||||
priv := NewPrivValidator(privAccounts[0], db_.NewMemDB())
|
||||
priv := NewPrivValidator(db_.NewMemDB(), privAccounts[0])
|
||||
cs.SetPrivValidator(priv)
|
||||
|
||||
blockHash := cs.RunActionPrecommit(1, 0)
|
||||
if blockHash != nil {
|
||||
t.Errorf("RunActionPrecommit should fail without a proposal")
|
||||
vote := cs.RunActionPrecommit(1, 0)
|
||||
if vote != nil {
|
||||
t.Errorf("RunActionPrecommit should return nil without a proposal")
|
||||
}
|
||||
|
||||
cs.RunActionPropose(1, 0)
|
||||
|
||||
// Test RunActionPrecommit failures:
|
||||
blockHash = cs.RunActionPrecommit(1, 1)
|
||||
if blockHash != nil {
|
||||
t.Errorf("RunActionPrecommit should fail for wrong round")
|
||||
}
|
||||
blockHash = cs.RunActionPrecommit(2, 0)
|
||||
if blockHash != nil {
|
||||
t.Errorf("RunActionPrecommit should fail for wrong height")
|
||||
}
|
||||
blockHash = cs.RunActionPrecommit(1, 0)
|
||||
if blockHash != nil {
|
||||
t.Errorf("RunActionPrecommit should fail, not enough prevotes")
|
||||
assertPanics(t, "Wrong height ", func() { cs.RunActionPrecommit(2, 0) })
|
||||
assertPanics(t, "Wrong round", func() { cs.RunActionPrecommit(1, 1) })
|
||||
vote = cs.RunActionPrecommit(1, 0)
|
||||
if vote != nil {
|
||||
t.Errorf("RunActionPrecommit should return nil, not enough prevotes")
|
||||
}
|
||||
|
||||
// Add at least +2/3 prevotes.
|
||||
@ -184,21 +182,15 @@ func TestRunActionPrecommitCommitFinalize(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test RunActionPrecommit success:
|
||||
blockHash = cs.RunActionPrecommit(1, 0)
|
||||
if len(blockHash) == 0 {
|
||||
vote = cs.RunActionPrecommit(1, 0)
|
||||
if vote == nil {
|
||||
t.Errorf("RunActionPrecommit should have succeeded")
|
||||
}
|
||||
checkRoundState(t, cs, 1, 0, RoundStepPrecommit)
|
||||
|
||||
// Test RunActionCommit failures:
|
||||
blockHash = cs.RunActionCommit(2)
|
||||
if blockHash != nil {
|
||||
t.Errorf("RunActionCommit should fail for wrong height")
|
||||
}
|
||||
blockHash = cs.RunActionCommit(1)
|
||||
if blockHash != nil {
|
||||
t.Errorf("RunActionCommit should fail, not enough commits")
|
||||
}
|
||||
assertPanics(t, "Wrong height ", func() { cs.RunActionCommit(2, 0) })
|
||||
assertPanics(t, "Wrong round", func() { cs.RunActionCommit(1, 1) })
|
||||
|
||||
// Add at least +2/3 precommits.
|
||||
for i := 0; i < 7; i++ {
|
||||
@ -213,8 +205,8 @@ func TestRunActionPrecommitCommitFinalize(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test RunActionCommit success:
|
||||
blockHash = cs.RunActionCommit(1)
|
||||
if len(blockHash) == 0 {
|
||||
vote = cs.RunActionCommit(1, 0)
|
||||
if vote == nil {
|
||||
t.Errorf("RunActionCommit should have succeeded")
|
||||
}
|
||||
checkRoundState(t, cs, 1, 0, RoundStepCommit)
|
||||
@ -237,13 +229,13 @@ func TestRunActionPrecommitCommitFinalize(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test RunActionCommitWait:
|
||||
cs.RunActionCommitWait(1)
|
||||
cs.RunActionCommitWait(1, 0)
|
||||
if cs.CommitTime.IsZero() {
|
||||
t.Errorf("Expected CommitTime to have been set")
|
||||
}
|
||||
checkRoundState(t, cs, 1, 0, RoundStepCommitWait)
|
||||
|
||||
// Test RunActionFinalize:
|
||||
cs.RunActionFinalize(1)
|
||||
cs.RunActionFinalize(1, 0)
|
||||
checkRoundState(t, cs, 2, 0, RoundStepStart)
|
||||
}
|
||||
|
@ -238,3 +238,13 @@ func (vs *VoteSet) StringWithIndent(indent string) string {
|
||||
indent, vs.votesBitArray,
|
||||
indent)
|
||||
}
|
||||
|
||||
func (vs *VoteSet) Description() string {
|
||||
if vs == nil {
|
||||
return "nil-VoteSet"
|
||||
}
|
||||
vs.mtx.Lock()
|
||||
defer vs.mtx.Unlock()
|
||||
return fmt.Sprintf(`VoteSet{H:%v R:%v T:%v %v}`,
|
||||
vs.height, vs.round, vs.type_, vs.votesBitArray)
|
||||
}
|
||||
|
31
gen_account.go
Normal file
31
gen_account.go
Normal file
@ -0,0 +1,31 @@
|
||||
// +build gen_account
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
||||
"github.com/tendermint/tendermint/config"
|
||||
"github.com/tendermint/tendermint/state"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
// Parse config flags
|
||||
config.ParseFlags()
|
||||
|
||||
// Generate private account
|
||||
privAccount := state.GenPrivAccount()
|
||||
|
||||
fmt.Printf(`Generated account:
|
||||
Account Public Key: %X
|
||||
(base64) %v
|
||||
Account Private Key: %X
|
||||
(base64) %v
|
||||
`,
|
||||
privAccount.PubKey,
|
||||
base64.StdEncoding.EncodeToString(privAccount.PubKey),
|
||||
privAccount.PrivKey,
|
||||
base64.StdEncoding.EncodeToString(privAccount.PrivKey))
|
||||
}
|
@ -170,7 +170,7 @@ func (sw *Switch) Broadcast(chId byte, msg Binary) (numSuccess, numFailure int)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug("Broadcast on [%X]", chId, msg)
|
||||
log.Debug("[%X] Broadcast: %v", chId, msg)
|
||||
for _, peer := range sw.peers.List() {
|
||||
success := peer.TrySend(chId, msg)
|
||||
log.Debug("Broadcast for peer %v success: %v", peer, success)
|
||||
|
@ -1,8 +1,10 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
. "github.com/tendermint/tendermint/binary"
|
||||
. "github.com/tendermint/tendermint/blocks"
|
||||
@ -138,6 +140,24 @@ func GenPrivAccount() *PrivAccount {
|
||||
}
|
||||
}
|
||||
|
||||
// The Account.Id is empty since it isn't in the blockchain.
|
||||
func PrivAccountFromJSON(jsonBlob []byte) (privAccount *PrivAccount) {
|
||||
err := json.Unmarshal(jsonBlob, &privAccount)
|
||||
if err != nil {
|
||||
Panicf("Couldn't read PrivAccount: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// The Account.Id is empty since it isn't in the blockchain.
|
||||
func PrivAccountFromFile(file string) *PrivAccount {
|
||||
jsonBlob, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
Panicf("Couldn't read PrivAccount from file: %v", err)
|
||||
}
|
||||
return PrivAccountFromJSON(jsonBlob)
|
||||
}
|
||||
|
||||
func (pa *PrivAccount) SignBytes(msg []byte) Signature {
|
||||
signature := crypto.SignMessage(msg, pa.PrivKey, pa.PubKey)
|
||||
sig := Signature{
|
||||
|
@ -16,7 +16,7 @@ type GenesisDoc struct {
|
||||
AccountDetails []*AccountDetail
|
||||
}
|
||||
|
||||
func ReadGenesisDocJSON(jsonBlob []byte) (genState *GenesisDoc) {
|
||||
func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) {
|
||||
err := json.Unmarshal(jsonBlob, &genState)
|
||||
if err != nil {
|
||||
Panicf("Couldn't read GenesisDoc: %v", err)
|
||||
@ -29,7 +29,7 @@ func GenesisStateFromFile(db db_.DB, genDocFile string) *State {
|
||||
if err != nil {
|
||||
Panicf("Couldn't read GenesisDoc file: %v", err)
|
||||
}
|
||||
genDoc := ReadGenesisDocJSON(jsonBlob)
|
||||
genDoc := GenesisDocFromJSON(jsonBlob)
|
||||
return GenesisStateFromDoc(db, genDoc)
|
||||
}
|
||||
|
||||
|
@ -81,6 +81,11 @@ func (vset *ValidatorSet) GetById(id uint64) (index uint32, val *Validator) {
|
||||
return
|
||||
}
|
||||
|
||||
func (vset *ValidatorSet) HasId(id uint64) bool {
|
||||
_, val_ := vset.validators.Get(id)
|
||||
return val_ != nil
|
||||
}
|
||||
|
||||
func (vset *ValidatorSet) GetByIndex(index uint32) (id uint64, val *Validator) {
|
||||
id_, val_ := vset.validators.GetByIndex(uint64(index))
|
||||
id, val = id_.(uint64), val_.(*Validator)
|
||||
|
@ -1,3 +1,5 @@
|
||||
// +build tendermintd
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -20,6 +22,7 @@ type Node struct {
|
||||
pexReactor *p2p.PEXReactor
|
||||
mempoolReactor *mempool_.MempoolReactor
|
||||
consensusReactor *consensus.ConsensusReactor
|
||||
privValidator *consensus.PrivValidator
|
||||
}
|
||||
|
||||
func NewNode() *Node {
|
||||
@ -34,6 +37,14 @@ func NewNode() *Node {
|
||||
state = state_.GenesisStateFromFile(stateDB, config.RootDir+"/genesis.json")
|
||||
}
|
||||
|
||||
// Get PrivAccount
|
||||
var privValidator *consensus.PrivValidator
|
||||
if _, err := os.Stat(config.RootDir + "/private.json"); os.IsExist(err) {
|
||||
privAccount := state_.PrivAccountFromFile(config.RootDir + "/private.json")
|
||||
privValidatorDB := db_.NewMemDB() // TODO configurable db.
|
||||
privValidator = consensus.NewPrivValidator(privValidatorDB, privAccount)
|
||||
}
|
||||
|
||||
// Get PEXReactor
|
||||
book := p2p.NewAddrBook(config.RootDir + "/addrbook.json")
|
||||
pexReactor := p2p.NewPEXReactor(book)
|
||||
@ -44,6 +55,9 @@ func NewNode() *Node {
|
||||
|
||||
// Get ConsensusReactor
|
||||
consensusReactor := consensus.NewConsensusReactor(blockStore, mempool, state)
|
||||
if privValidator != nil {
|
||||
consensusReactor.SetPrivValidator(privValidator)
|
||||
}
|
||||
|
||||
sw := p2p.NewSwitch([]p2p.Reactor{pexReactor, mempoolReactor, consensusReactor})
|
||||
|
||||
@ -53,6 +67,7 @@ func NewNode() *Node {
|
||||
pexReactor: pexReactor,
|
||||
mempoolReactor: mempoolReactor,
|
||||
consensusReactor: consensusReactor,
|
||||
privValidator: privValidator,
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user