From 647d26f7a0277583937ad18c589986ffff8af03b Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 24 Oct 2014 14:37:12 -0700 Subject: [PATCH] consensus cleanup, privValidator config --- consensus/priv_validator.go | 6 +-- consensus/reactor.go | 84 +++++++++++++------------------------ consensus/state.go | 75 ++++++++++++++++++++++----------- consensus/state_test.go | 66 +++++++++++++---------------- consensus/vote_set.go | 10 +++++ gen_account.go | 31 ++++++++++++++ p2p/switch.go | 2 +- state/account.go | 20 +++++++++ state/genesis.go | 4 +- state/validator_set.go | 5 +++ main.go => tendermintd.go | 15 +++++++ 11 files changed, 197 insertions(+), 121 deletions(-) create mode 100644 gen_account.go rename main.go => tendermintd.go (86%) diff --git a/consensus/priv_validator.go b/consensus/priv_validator.go index 929d38264..a7f19e9f5 100644 --- a/consensus/priv_validator.go +++ b/consensus/priv_validator.go @@ -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. diff --git a/consensus/reactor.go b/consensus/reactor.go index d62f6f79b..b7129f45e 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -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) } //------------------------------------- diff --git a/consensus/state.go b/consensus/state.go index 107133fc3..d6988f9f7 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -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 +} diff --git a/consensus/state_test.go b/consensus/state_test.go index 06cea1fc4..bb53e4593 100644 --- a/consensus/state_test.go +++ b/consensus/state_test.go @@ -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) } diff --git a/consensus/vote_set.go b/consensus/vote_set.go index 1d9fd7c73..bd853e912 100644 --- a/consensus/vote_set.go +++ b/consensus/vote_set.go @@ -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) +} diff --git a/gen_account.go b/gen_account.go new file mode 100644 index 000000000..9f8745774 --- /dev/null +++ b/gen_account.go @@ -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)) +} diff --git a/p2p/switch.go b/p2p/switch.go index 57433a753..e6ae384c1 100644 --- a/p2p/switch.go +++ b/p2p/switch.go @@ -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) diff --git a/state/account.go b/state/account.go index ec4450a14..9cd1a0082 100644 --- a/state/account.go +++ b/state/account.go @@ -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{ diff --git a/state/genesis.go b/state/genesis.go index fe6307fee..e81106bb0 100644 --- a/state/genesis.go +++ b/state/genesis.go @@ -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) } diff --git a/state/validator_set.go b/state/validator_set.go index 560993d0e..1b102a9dc 100644 --- a/state/validator_set.go +++ b/state/validator_set.go @@ -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) diff --git a/main.go b/tendermintd.go similarity index 86% rename from main.go rename to tendermintd.go index 3d74e925f..58528a724 100644 --- a/main.go +++ b/tendermintd.go @@ -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, } }