Merge pull request #3347 from LeoHChen/unify_viewID

Unify viewID in consensus
pull/3351/head
Leo Chen 4 years ago committed by GitHub
commit 421eeed778
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      api/proto/message/message.pb.go
  2. 2
      api/service/syncing/downloader/proto/downloader.pb.go
  3. 2
      cmd/harmony/main.go
  4. 36
      consensus/checks.go
  5. 3
      consensus/consensus.go
  6. 52
      consensus/consensus_service.go
  7. 10
      consensus/consensus_service_test.go
  8. 4
      consensus/consensus_test.go
  9. 38
      consensus/consensus_v2.go
  10. 48
      consensus/consensus_viewchange_msg.go
  11. 2
      consensus/construct.go
  12. 4
      consensus/construct_test.go
  13. 21
      consensus/debug.go
  14. 5
      consensus/leader.go
  15. 101
      consensus/view_change.go
  16. 14
      consensus/view_change_test.go
  17. 2
      go.mod
  18. 7
      hmy/hmy.go
  19. 20
      node/api.go
  20. 6
      node/node.go
  21. 2
      node/node_newblock.go
  22. 28
      rpc/debug.go
  23. 2
      scripts/install_build_tools.sh
  24. 1
      scripts/install_protoc.sh

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.23.0 // protoc-gen-go v1.23.0
// protoc v3.6.1 // protoc v3.12.3
// source: message.proto // source: message.proto
package message package message

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.23.0 // protoc-gen-go v1.23.0
// protoc v3.6.1 // protoc v3.12.3
// source: downloader.proto // source: downloader.proto
package downloader package downloader

@ -600,7 +600,7 @@ func setupConsensusAndNode(hc harmonyConfig, nodeConfig *nodeconfig.ConfigType)
// Set the consensus ID to be the current block number // Set the consensus ID to be the current block number
viewID := currentNode.Blockchain().CurrentBlock().Header().ViewID().Uint64() viewID := currentNode.Blockchain().CurrentBlock().Header().ViewID().Uint64()
currentConsensus.SetViewID(viewID + 1) currentConsensus.SetViewIDs(viewID + 1)
utils.Logger().Info(). utils.Logger().Info().
Uint64("viewID", viewID). Uint64("viewID", viewID).
Msg("Init Blockchain") Msg("Init Blockchain")

@ -57,7 +57,7 @@ func (consensus *Consensus) senderKeySanityChecks(msg *msg_pb.Message, senderKey
func (consensus *Consensus) isRightBlockNumAndViewID(recvMsg *FBFTMessage, func (consensus *Consensus) isRightBlockNumAndViewID(recvMsg *FBFTMessage,
) bool { ) bool {
if recvMsg.ViewID != consensus.viewID || recvMsg.BlockNum != consensus.blockNum { if recvMsg.ViewID != consensus.GetCurViewID() || recvMsg.BlockNum != consensus.blockNum {
consensus.getLogger().Debug(). consensus.getLogger().Debug().
Uint64("MsgViewID", recvMsg.ViewID). Uint64("MsgViewID", recvMsg.ViewID).
Uint64("MsgBlockNum", recvMsg.BlockNum). Uint64("MsgBlockNum", recvMsg.BlockNum).
@ -96,7 +96,7 @@ func (consensus *Consensus) onAnnounceSanityChecks(recvMsg *FBFTMessage) bool {
"[OnAnnounce] Already in ViewChanging mode, conflicing announce, doing noop", "[OnAnnounce] Already in ViewChanging mode, conflicing announce, doing noop",
) )
} else { } else {
consensus.startViewChange(consensus.viewID + 1) consensus.startViewChange(consensus.GetCurViewID() + 1)
} }
} }
consensus.getLogger().Debug(). consensus.getLogger().Debug().
@ -162,51 +162,53 @@ func (consensus *Consensus) onPreparedSanityChecks(
return true return true
} }
// TODO: leo: move the sanity check to p2p message validation
func (consensus *Consensus) onViewChangeSanityCheck(recvMsg *FBFTMessage) bool { func (consensus *Consensus) onViewChangeSanityCheck(recvMsg *FBFTMessage) bool {
// TODO: if difference is only one, new leader can still propose the same committed block to avoid another view change // TODO: if difference is only one, new leader can still propose the same committed block to avoid another view change
// TODO: new leader catchup without ignore view change message // TODO: new leader catchup without ignore view change message
consensus.getLogger().Info().
Uint64("MsgBlockNum", recvMsg.BlockNum).
Uint64("MyViewChangingID", consensus.GetViewChangingID()).
Uint64("MsgViewChangingID", recvMsg.ViewID).
Msg("onViewChange")
if consensus.blockNum > recvMsg.BlockNum { if consensus.blockNum > recvMsg.BlockNum {
consensus.getLogger().Debug(). consensus.getLogger().Debug().
Uint64("MsgBlockNum", recvMsg.BlockNum).
Msg("[onViewChange] Message BlockNum Is Low") Msg("[onViewChange] Message BlockNum Is Low")
return false return false
} }
if consensus.blockNum < recvMsg.BlockNum { if consensus.blockNum < recvMsg.BlockNum {
consensus.getLogger().Warn(). consensus.getLogger().Warn().
Uint64("MsgBlockNum", recvMsg.BlockNum).
Msg("[onViewChange] New Leader Has Lower Blocknum") Msg("[onViewChange] New Leader Has Lower Blocknum")
return false return false
} }
if consensus.IsViewChangingMode() && if consensus.IsViewChangingMode() &&
consensus.current.ViewID() > recvMsg.ViewID { consensus.GetViewChangingID() > recvMsg.ViewID {
consensus.getLogger().Warn(). consensus.getLogger().Warn().
Uint64("MyViewChangingID", consensus.current.ViewID()).
Uint64("MsgViewChangingID", recvMsg.ViewID).
Msg("[onViewChange] ViewChanging ID Is Low") Msg("[onViewChange] ViewChanging ID Is Low")
return false return false
} }
if recvMsg.ViewID-consensus.current.ViewID() > MaxViewIDDiff { if recvMsg.ViewID-consensus.GetViewChangingID() > MaxViewIDDiff {
consensus.getLogger().Debug(). consensus.getLogger().Debug().
Uint64("MsgViewID", recvMsg.ViewID).
Uint64("CurrentViewID", consensus.current.ViewID()).
Msg("Received viewID that is MaxViewIDDiff (100) further from the current viewID!") Msg("Received viewID that is MaxViewIDDiff (100) further from the current viewID!")
return false return false
} }
if len(recvMsg.SenderPubkeys) != 1 {
consensus.getLogger().Error().Msg("[onViewChange] multiple signers in view change message.")
return false
}
return true return true
} }
// TODO: leo: move the sanity check to p2p message validation
func (consensus *Consensus) onNewViewSanityCheck(recvMsg *FBFTMessage) bool { func (consensus *Consensus) onNewViewSanityCheck(recvMsg *FBFTMessage) bool {
if recvMsg.ViewID < consensus.viewID { if recvMsg.ViewID < consensus.GetCurViewID() {
consensus.getLogger().Warn(). consensus.getLogger().Warn().
Uint64("LastSuccessfulConsensusViewID", consensus.viewID). Uint64("LastSuccessfulConsensusViewID", consensus.GetCurViewID()).
Uint64("MsgViewChangingID", recvMsg.ViewID). Uint64("MsgViewChangingID", recvMsg.ViewID).
Msg("[onNewView] ViewID should be larger than the viewID of the last successful consensus") Msg("[onNewView] ViewID should be larger than the viewID of the last successful consensus")
return false return false
} }
if !consensus.IsViewChangingMode() {
consensus.getLogger().Warn().
Msg("[onNewView] Not in ViewChanging mode, ignoring the new view message")
return false
}
return true return true
} }

@ -77,7 +77,6 @@ type Consensus struct {
// blockNum: the next blockNumber that FBFT is going to agree on, // blockNum: the next blockNumber that FBFT is going to agree on,
// should be equal to the blockNumber of next block // should be equal to the blockNumber of next block
blockNum uint64 blockNum uint64
viewID uint64
// Blockhash - 32 byte // Blockhash - 32 byte
blockHash [32]byte blockHash [32]byte
// Block to run consensus on // Block to run consensus on
@ -199,7 +198,7 @@ func New(
// viewID has to be initialized as the height of // viewID has to be initialized as the height of
// the blockchain during initialization as it was // the blockchain during initialization as it was
// displayed on explorer as Height right now // displayed on explorer as Height right now
consensus.viewID = 0 consensus.SetCurViewID(0)
consensus.ShardID = shard consensus.ShardID = shard
consensus.syncReadyChan = make(chan struct{}) consensus.syncReadyChan = make(chan struct{})
consensus.syncNotReadyChan = make(chan struct{}) consensus.syncNotReadyChan = make(chan struct{})

@ -72,11 +72,6 @@ func (consensus *Consensus) signAndMarshalConsensusMessage(message *msg_pb.Messa
return marshaledMessage, nil return marshaledMessage, nil
} }
// GetViewID returns the consensus ID
func (consensus *Consensus) GetViewID() uint64 {
return consensus.viewID
}
// UpdatePublicKeys updates the PublicKeys for // UpdatePublicKeys updates the PublicKeys for
// quorum on current subcommittee, protected by a mutex // quorum on current subcommittee, protected by a mutex
func (consensus *Consensus) UpdatePublicKeys(pubKeys []bls_cosi.PublicKeyWrapper) int64 { func (consensus *Consensus) UpdatePublicKeys(pubKeys []bls_cosi.PublicKeyWrapper) int64 {
@ -199,12 +194,6 @@ func (consensus *Consensus) IsValidatorInCommittee(pubKey bls.SerializedPublicKe
return consensus.Decider.IndexOf(pubKey) != -1 return consensus.Decider.IndexOf(pubKey) != -1
} }
// SetViewID set the viewID to the height of the blockchain
func (consensus *Consensus) SetViewID(height uint64) {
consensus.viewID = height
consensus.current.viewID = height
}
// SetMode sets the mode of consensus // SetMode sets the mode of consensus
func (consensus *Consensus) SetMode(m Mode) { func (consensus *Consensus) SetMode(m Mode) {
consensus.current.SetMode(m) consensus.current.SetMode(m)
@ -232,26 +221,20 @@ func (consensus *Consensus) checkViewID(msg *FBFTMessage) error {
//in syncing mode, node accepts incoming messages without viewID/leaderKey checking //in syncing mode, node accepts incoming messages without viewID/leaderKey checking
//so only set mode to normal when new node enters consensus and need checking viewID //so only set mode to normal when new node enters consensus and need checking viewID
consensus.current.SetMode(Normal) consensus.current.SetMode(Normal)
consensus.viewID = msg.ViewID consensus.SetViewIDs(msg.ViewID)
consensus.current.SetViewID(msg.ViewID)
if len(msg.SenderPubkeys) != 1 { if len(msg.SenderPubkeys) != 1 {
return errors.New("Leader message can not have multiple sender keys") return errors.New("Leader message can not have multiple sender keys")
} }
consensus.LeaderPubKey = msg.SenderPubkeys[0] consensus.LeaderPubKey = msg.SenderPubkeys[0]
consensus.IgnoreViewIDCheck.UnSet() consensus.IgnoreViewIDCheck.UnSet()
consensus.consensusTimeout[timeoutConsensus].Start() consensus.consensusTimeout[timeoutConsensus].Start()
utils.Logger().Debug(). consensus.getLogger().Debug().
Uint64("viewID", consensus.viewID).
Str("leaderKey", consensus.LeaderPubKey.Bytes.Hex()). Str("leaderKey", consensus.LeaderPubKey.Bytes.Hex()).
Msg("viewID and leaderKey override")
utils.Logger().Debug().
Uint64("viewID", consensus.viewID).
Uint64("block", consensus.blockNum).
Msg("Start consensus timer") Msg("Start consensus timer")
return nil return nil
} else if msg.ViewID > consensus.viewID { } else if msg.ViewID > consensus.GetCurViewID() {
return consensus_engine.ErrViewIDNotMatch return consensus_engine.ErrViewIDNotMatch
} else if msg.ViewID < consensus.viewID { } else if msg.ViewID < consensus.GetCurViewID() {
return errors.New("view ID belongs to the past") return errors.New("view ID belongs to the past")
} }
return nil return nil
@ -282,7 +265,7 @@ func (consensus *Consensus) ReadSignatureBitmapPayload(
func (consensus *Consensus) getLogger() *zerolog.Logger { func (consensus *Consensus) getLogger() *zerolog.Logger {
logger := utils.Logger().With(). logger := utils.Logger().With().
Uint64("myBlock", consensus.blockNum). Uint64("myBlock", consensus.blockNum).
Uint64("myViewID", consensus.viewID). Uint64("myViewID", consensus.GetCurViewID()).
Interface("phase", consensus.phase). Interface("phase", consensus.phase).
Str("mode", consensus.current.Mode().String()). Str("mode", consensus.current.Mode().String()).
Logger() Logger()
@ -470,12 +453,12 @@ func (consensus *Consensus) UpdateConsensusInformation() Mode {
if len(curHeader.ShardState()) == 0 && curHeader.Number().Uint64() != 0 { if len(curHeader.ShardState()) == 0 && curHeader.Number().Uint64() != 0 {
leaderPubKey, err := consensus.getLeaderPubKeyFromCoinbase(curHeader) leaderPubKey, err := consensus.getLeaderPubKeyFromCoinbase(curHeader)
if err != nil || leaderPubKey == nil { if err != nil || leaderPubKey == nil {
consensus.getLogger().Debug().Err(err). consensus.getLogger().Error().Err(err).
Msg("[UpdateConsensusInformation] Unable to get leaderPubKey from coinbase") Msg("[UpdateConsensusInformation] Unable to get leaderPubKey from coinbase")
consensus.IgnoreViewIDCheck.Set() consensus.IgnoreViewIDCheck.Set()
hasError = true hasError = true
} else { } else {
consensus.getLogger().Debug(). consensus.getLogger().Info().
Str("leaderPubKey", leaderPubKey.Bytes.Hex()). Str("leaderPubKey", leaderPubKey.Bytes.Hex()).
Msg("[UpdateConsensusInformation] Most Recent LeaderPubKey Updated Based on BlockChain") Msg("[UpdateConsensusInformation] Most Recent LeaderPubKey Updated Based on BlockChain")
consensus.LeaderPubKey = leaderPubKey consensus.LeaderPubKey = leaderPubKey
@ -494,10 +477,8 @@ func (consensus *Consensus) UpdateConsensusInformation() Mode {
if (oldLeader != nil && consensus.LeaderPubKey != nil && if (oldLeader != nil && consensus.LeaderPubKey != nil &&
!consensus.LeaderPubKey.Object.IsEqual(oldLeader.Object)) && consensus.IsLeader() { !consensus.LeaderPubKey.Object.IsEqual(oldLeader.Object)) && consensus.IsLeader() {
go func() { go func() {
utils.Logger().Debug(). consensus.getLogger().Info().
Str("myKey", myPubKeys.SerializeToHexStr()). Str("myKey", myPubKeys.SerializeToHexStr()).
Uint64("viewID", consensus.viewID).
Uint64("block", consensus.blockNum).
Msg("[UpdateConsensusInformation] I am the New Leader") Msg("[UpdateConsensusInformation] I am the New Leader")
consensus.ReadySignal <- struct{}{} consensus.ReadySignal <- struct{}{}
}() }()
@ -553,3 +534,20 @@ func (consensus *Consensus) addViewIDKeyIfNotExist(viewID uint64) {
consensus.viewIDBitmap[viewID] = viewIDBitmap consensus.viewIDBitmap[viewID] = viewIDBitmap
} }
} }
// SetViewIDs set both current view ID and view changing ID to the height
// of the blockchain. It is used during client startup to recover the state
func (consensus *Consensus) SetViewIDs(height uint64) {
consensus.SetCurViewID(height)
consensus.SetViewChangingID(height)
}
// SetCurViewID set the current view ID
func (consensus *Consensus) SetCurViewID(viewID uint64) {
consensus.current.SetCurViewID(viewID)
}
// SetViewChangingID set the current view change ID
func (consensus *Consensus) SetViewChangingID(viewID uint64) {
consensus.current.SetViewChangingID(viewID)
}

@ -31,7 +31,7 @@ func TestPopulateMessageFields(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Cannot craeate consensus: %v", err) t.Fatalf("Cannot craeate consensus: %v", err)
} }
consensus.viewID = 2 consensus.SetCurViewID(2)
blockHash := [32]byte{} blockHash := [32]byte{}
consensus.blockHash = blockHash consensus.blockHash = blockHash
@ -72,7 +72,7 @@ func TestSignAndMarshalConsensusMessage(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Cannot craeate consensus: %v", err) t.Fatalf("Cannot craeate consensus: %v", err)
} }
consensus.viewID = 2 consensus.SetCurViewID(2)
consensus.blockHash = [32]byte{} consensus.blockHash = [32]byte{}
msg := &msg_pb.Message{} msg := &msg_pb.Message{}
@ -105,8 +105,8 @@ func TestSetViewID(t *testing.T) {
} }
height := uint64(1000) height := uint64(1000)
consensus.SetViewID(height) consensus.SetViewIDs(height)
if consensus.viewID != height { if consensus.GetCurViewID() != height {
t.Errorf("Cannot set consensus ID. Got: %v, Expected: %v", consensus.viewID, height) t.Errorf("Cannot set consensus ID. Got: %v, Expected: %v", consensus.GetCurViewID(), height)
} }
} }

@ -43,7 +43,7 @@ func TestConsensusInitialization(t *testing.T) {
// State / consensus.current // State / consensus.current
assert.Equal(t, state.mode, consensus.current.mode) assert.Equal(t, state.mode, consensus.current.mode)
assert.Equal(t, state.viewID, consensus.current.viewID) assert.Equal(t, state.GetViewChangingID(), consensus.current.GetViewChangingID())
// FBFT timeout // FBFT timeout
assert.IsType(t, make(map[TimeoutType]*utils.Timeout), consensus.consensusTimeout) assert.IsType(t, make(map[TimeoutType]*utils.Timeout), consensus.consensusTimeout)
@ -58,7 +58,7 @@ func TestConsensusInitialization(t *testing.T) {
assert.Equal(t, multiBLSPrivateKey.GetPublicKeys(), consensus.GetPublicKeys()) assert.Equal(t, multiBLSPrivateKey.GetPublicKeys(), consensus.GetPublicKeys())
// Misc // Misc
assert.Equal(t, uint64(0), consensus.viewID) assert.Equal(t, uint64(0), consensus.GetViewChangingID())
assert.Equal(t, uint32(shard.BeaconChainShardID), consensus.ShardID) assert.Equal(t, uint32(shard.BeaconChainShardID), consensus.ShardID)
assert.IsType(t, make(chan struct{}), consensus.syncReadyChan) assert.IsType(t, make(chan struct{}), consensus.syncReadyChan)

@ -163,9 +163,9 @@ func (consensus *Consensus) finalizeCommits() {
if consensus.consensusTimeout[timeoutBootstrap].IsActive() { if consensus.consensusTimeout[timeoutBootstrap].IsActive() {
consensus.consensusTimeout[timeoutBootstrap].Stop() consensus.consensusTimeout[timeoutBootstrap].Stop()
consensus.getLogger().Debug().Msg("[finalizeCommits] Start consensus timer; stop bootstrap timer only once") consensus.getLogger().Info().Msg("[finalizeCommits] Start consensus timer; stop bootstrap timer only once")
} else { } else {
consensus.getLogger().Debug().Msg("[finalizeCommits] Start consensus timer") consensus.getLogger().Info().Msg("[finalizeCommits] Start consensus timer")
} }
consensus.consensusTimeout[timeoutConsensus].Start() consensus.consensusTimeout[timeoutConsensus].Start()
@ -179,7 +179,7 @@ func (consensus *Consensus) finalizeCommits() {
Msg("HOORAY!!!!!!! CONSENSUS REACHED!!!!!!!") Msg("HOORAY!!!!!!! CONSENSUS REACHED!!!!!!!")
// Sleep to wait for the full block time // Sleep to wait for the full block time
consensus.getLogger().Debug().Msg("[finalizeCommits] Waiting for Block Time") consensus.getLogger().Info().Msg("[finalizeCommits] Waiting for Block Time")
<-time.After(time.Until(consensus.NextBlockDue)) <-time.After(time.Until(consensus.NextBlockDue))
// Send signal to Node to propose the new block for consensus // Send signal to Node to propose the new block for consensus
@ -281,7 +281,7 @@ func (consensus *Consensus) tryCatchup() {
consensus.getLogger().Info().Msg("[TryCatchup] block found to commit") consensus.getLogger().Info().Msg("[TryCatchup] block found to commit")
atomic.AddUint64(&consensus.blockNum, 1) atomic.AddUint64(&consensus.blockNum, 1)
atomic.StoreUint64(&consensus.viewID, committedMsg.ViewID+1) consensus.SetCurViewID(committedMsg.ViewID + 1)
consensus.LeaderPubKey = committedMsg.SenderPubkeys[0] consensus.LeaderPubKey = committedMsg.SenderPubkeys[0]
@ -344,10 +344,7 @@ func (consensus *Consensus) Start(
ticker := time.NewTicker(3 * time.Second) ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop() defer ticker.Stop()
consensus.consensusTimeout[timeoutBootstrap].Start() consensus.consensusTimeout[timeoutBootstrap].Start()
consensus.getLogger().Debug(). consensus.getLogger().Info().Msg("[ConsensusMainLoop] Start bootstrap timeout (only once)")
Uint64("viewID", consensus.viewID).
Uint64("blockNum", consensus.blockNum).
Msg("[ConsensusMainLoop] Start bootstrap timeout (only once)")
vdfInProgress := false vdfInProgress := false
// Set up next block due time. // Set up next block due time.
@ -371,26 +368,27 @@ func (consensus *Consensus) Start(
continue continue
} }
if k != timeoutViewChange { if k != timeoutViewChange {
consensus.getLogger().Debug().Msg("[ConsensusMainLoop] Ops Consensus Timeout!!!") consensus.getLogger().Warn().Msg("[ConsensusMainLoop] Ops Consensus Timeout!!!")
consensus.startViewChange(consensus.viewID + 1) viewID := consensus.GetCurViewID()
consensus.startViewChange(viewID + 1)
break break
} else { } else {
consensus.getLogger().Debug().Msg("[ConsensusMainLoop] Ops View Change Timeout!!!") consensus.getLogger().Warn().Msg("[ConsensusMainLoop] Ops View Change Timeout!!!")
viewID := consensus.current.ViewID() viewID := consensus.GetViewChangingID()
consensus.startViewChange(viewID + 1) consensus.startViewChange(viewID + 1)
break break
} }
} }
case <-consensus.syncReadyChan: case <-consensus.syncReadyChan:
consensus.getLogger().Debug().Msg("[ConsensusMainLoop] syncReadyChan") consensus.getLogger().Info().Msg("[ConsensusMainLoop] syncReadyChan")
consensus.SetBlockNum(consensus.ChainReader.CurrentHeader().Number().Uint64() + 1) consensus.SetBlockNum(consensus.ChainReader.CurrentHeader().Number().Uint64() + 1)
consensus.SetViewID(consensus.ChainReader.CurrentHeader().ViewID().Uint64() + 1) consensus.SetViewIDs(consensus.ChainReader.CurrentHeader().ViewID().Uint64() + 1)
mode := consensus.UpdateConsensusInformation() mode := consensus.UpdateConsensusInformation()
consensus.current.SetMode(mode) consensus.current.SetMode(mode)
consensus.getLogger().Info().Str("Mode", mode.String()).Msg("Node is IN SYNC") consensus.getLogger().Info().Str("Mode", mode.String()).Msg("Node is IN SYNC")
case <-consensus.syncNotReadyChan: case <-consensus.syncNotReadyChan:
consensus.getLogger().Debug().Msg("[ConsensusMainLoop] syncNotReadyChan") consensus.getLogger().Info().Msg("[ConsensusMainLoop] syncNotReadyChan")
consensus.SetBlockNum(consensus.ChainReader.CurrentHeader().Number().Uint64() + 1) consensus.SetBlockNum(consensus.ChainReader.CurrentHeader().Number().Uint64() + 1)
consensus.current.SetMode(Syncing) consensus.current.SetMode(Syncing)
consensus.getLogger().Info().Msg("[ConsensusMainLoop] Node is OUT OF SYNC") consensus.getLogger().Info().Msg("[ConsensusMainLoop] Node is OUT OF SYNC")
@ -476,7 +474,7 @@ func (consensus *Consensus) Start(
startTime = time.Now() startTime = time.Now()
consensus.msgSender.Reset(newBlock.NumberU64()) consensus.msgSender.Reset(newBlock.NumberU64())
consensus.getLogger().Debug(). consensus.getLogger().Info().
Int("numTxs", len(newBlock.Transactions())). Int("numTxs", len(newBlock.Transactions())).
Int("numStakingTxs", len(newBlock.StakingTransactions())). Int("numStakingTxs", len(newBlock.StakingTransactions())).
Time("startTime", startTime). Time("startTime", startTime).
@ -485,23 +483,23 @@ func (consensus *Consensus) Start(
consensus.announce(newBlock) consensus.announce(newBlock)
case viewID := <-consensus.commitFinishChan: case viewID := <-consensus.commitFinishChan:
consensus.getLogger().Debug().Msg("[ConsensusMainLoop] commitFinishChan") consensus.getLogger().Info().Msg("[ConsensusMainLoop] commitFinishChan")
// Only Leader execute this condition // Only Leader execute this condition
func() { func() {
consensus.mutex.Lock() consensus.mutex.Lock()
defer consensus.mutex.Unlock() defer consensus.mutex.Unlock()
if viewID == consensus.viewID { if viewID == consensus.GetCurViewID() {
consensus.finalizeCommits() consensus.finalizeCommits()
} }
}() }()
case <-stopChan: case <-stopChan:
consensus.getLogger().Debug().Msg("[ConsensusMainLoop] stopChan") consensus.getLogger().Info().Msg("[ConsensusMainLoop] stopChan")
return return
} }
} }
consensus.getLogger().Debug().Msg("[ConsensusMainLoop] Ended.") consensus.getLogger().Info().Msg("[ConsensusMainLoop] Ended.")
}() }()
} }

@ -10,7 +10,6 @@ import (
"github.com/harmony-one/harmony/api/proto" "github.com/harmony-one/harmony/api/proto"
msg_pb "github.com/harmony-one/harmony/api/proto/message" msg_pb "github.com/harmony-one/harmony/api/proto/message"
bls_cosi "github.com/harmony-one/harmony/crypto/bls" bls_cosi "github.com/harmony-one/harmony/crypto/bls"
"github.com/harmony-one/harmony/internal/utils"
) )
// construct the view change message // construct the view change message
@ -19,20 +18,16 @@ func (consensus *Consensus) constructViewChangeMessage(priKey *bls.PrivateKeyWra
ServiceType: msg_pb.ServiceType_CONSENSUS, ServiceType: msg_pb.ServiceType_CONSENSUS,
Type: msg_pb.MessageType_VIEWCHANGE, Type: msg_pb.MessageType_VIEWCHANGE,
Request: &msg_pb.Message_Viewchange{ Request: &msg_pb.Message_Viewchange{
Viewchange: &msg_pb.ViewChangeRequest{}, Viewchange: &msg_pb.ViewChangeRequest{
ViewId: consensus.GetViewChangingID(),
BlockNum: consensus.blockNum,
ShardId: consensus.ShardID,
SenderPubkey: priKey.Pub.Bytes[:],
LeaderPubkey: consensus.LeaderPubKey.Bytes[:],
},
}, },
} }
vcMsg := message.GetViewchange()
vcMsg.ViewId = consensus.current.ViewID()
vcMsg.BlockNum = consensus.blockNum
vcMsg.ShardId = consensus.ShardID
// sender address
vcMsg.SenderPubkey = priKey.Pub.Bytes[:]
// next leader key already updated
vcMsg.LeaderPubkey = consensus.LeaderPubKey.Bytes[:]
preparedMsgs := consensus.FBFTLog.GetMessagesByTypeSeq( preparedMsgs := consensus.FBFTLog.GetMessagesByTypeSeq(
msg_pb.MessageType_PREPARED, consensus.blockNum, msg_pb.MessageType_PREPARED, consensus.blockNum,
) )
@ -41,7 +36,7 @@ func (consensus *Consensus) constructViewChangeMessage(priKey *bls.PrivateKeyWra
var encodedBlock []byte var encodedBlock []byte
if preparedMsg != nil { if preparedMsg != nil {
block := consensus.FBFTLog.GetBlockByHash(preparedMsg.BlockHash) block := consensus.FBFTLog.GetBlockByHash(preparedMsg.BlockHash)
utils.Logger().Debug(). consensus.getLogger().Debug().
Interface("Block", block). Interface("Block", block).
Interface("preparedMsg", preparedMsg). Interface("preparedMsg", preparedMsg).
Msg("[constructViewChangeMessage] found prepared msg") Msg("[constructViewChangeMessage] found prepared msg")
@ -58,6 +53,7 @@ func (consensus *Consensus) constructViewChangeMessage(priKey *bls.PrivateKeyWra
} }
} }
vcMsg := message.GetViewchange()
var msgToSign []byte var msgToSign []byte
if len(encodedBlock) == 0 { if len(encodedBlock) == 0 {
msgToSign = NIL // m2 type message msgToSign = NIL // m2 type message
@ -69,7 +65,7 @@ func (consensus *Consensus) constructViewChangeMessage(priKey *bls.PrivateKeyWra
vcMsg.PreparedBlock = encodedBlock vcMsg.PreparedBlock = encodedBlock
} }
utils.Logger().Debug(). consensus.getLogger().Debug().
Hex("m1Payload", vcMsg.Payload). Hex("m1Payload", vcMsg.Payload).
Str("pubKey", consensus.GetPublicKeys().SerializeToHexStr()). Str("pubKey", consensus.GetPublicKeys().SerializeToHexStr()).
Msg("[constructViewChangeMessage]") Msg("[constructViewChangeMessage]")
@ -78,21 +74,21 @@ func (consensus *Consensus) constructViewChangeMessage(priKey *bls.PrivateKeyWra
if sign != nil { if sign != nil {
vcMsg.ViewchangeSig = sign.Serialize() vcMsg.ViewchangeSig = sign.Serialize()
} else { } else {
utils.Logger().Error().Msg("unable to serialize m1/m2 view change message signature") consensus.getLogger().Error().Msg("unable to serialize m1/m2 view change message signature")
} }
viewIDBytes := make([]byte, 8) viewIDBytes := make([]byte, 8)
binary.LittleEndian.PutUint64(viewIDBytes, consensus.current.ViewID()) binary.LittleEndian.PutUint64(viewIDBytes, consensus.GetViewChangingID())
sign1 := priKey.Pri.SignHash(viewIDBytes) sign1 := priKey.Pri.SignHash(viewIDBytes)
if sign1 != nil { if sign1 != nil {
vcMsg.ViewidSig = sign1.Serialize() vcMsg.ViewidSig = sign1.Serialize()
} else { } else {
utils.Logger().Error().Msg("unable to serialize viewID signature") consensus.getLogger().Error().Msg("unable to serialize viewID signature")
} }
marshaledMessage, err := consensus.signAndMarshalConsensusMessage(message, priKey.Pri) marshaledMessage, err := consensus.signAndMarshalConsensusMessage(message, priKey.Pri)
if err != nil { if err != nil {
utils.Logger().Error().Err(err). consensus.getLogger().Err(err).
Msg("[constructViewChangeMessage] failed to sign and marshal the viewchange message") Msg("[constructViewChangeMessage] failed to sign and marshal the viewchange message")
} }
return proto.ConstructConsensusMessage(marshaledMessage) return proto.ConstructConsensusMessage(marshaledMessage)
@ -104,16 +100,16 @@ func (consensus *Consensus) constructNewViewMessage(viewID uint64, priKey *bls.P
ServiceType: msg_pb.ServiceType_CONSENSUS, ServiceType: msg_pb.ServiceType_CONSENSUS,
Type: msg_pb.MessageType_NEWVIEW, Type: msg_pb.MessageType_NEWVIEW,
Request: &msg_pb.Message_Viewchange{ Request: &msg_pb.Message_Viewchange{
Viewchange: &msg_pb.ViewChangeRequest{}, Viewchange: &msg_pb.ViewChangeRequest{
ViewId: consensus.GetViewChangingID(),
BlockNum: consensus.blockNum,
ShardId: consensus.ShardID,
SenderPubkey: priKey.Pub.Bytes[:],
},
}, },
} }
vcMsg := message.GetViewchange() vcMsg := message.GetViewchange()
vcMsg.ViewId = consensus.current.ViewID()
vcMsg.BlockNum = consensus.blockNum
vcMsg.ShardId = consensus.ShardID
// sender address
vcMsg.SenderPubkey = priKey.Pub.Bytes[:]
vcMsg.Payload = consensus.m1Payload vcMsg.Payload = consensus.m1Payload
if len(consensus.m1Payload) != 0 { if len(consensus.m1Payload) != 0 {
block := consensus.FBFTLog.GetBlockByHash(consensus.blockHash) block := consensus.FBFTLog.GetBlockByHash(consensus.blockHash)
@ -129,7 +125,7 @@ func (consensus *Consensus) constructNewViewMessage(viewID uint64, priKey *bls.P
} }
sig2arr := consensus.GetNilSigsArray(viewID) sig2arr := consensus.GetNilSigsArray(viewID)
utils.Logger().Debug().Int("len", len(sig2arr)).Msg("[constructNewViewMessage] M2 (NIL) type signatures") consensus.getLogger().Debug().Int("len", len(sig2arr)).Msg("[constructNewViewMessage] M2 (NIL) type signatures")
if len(sig2arr) > 0 { if len(sig2arr) > 0 {
m2Sig := bls_cosi.AggregateSig(sig2arr) m2Sig := bls_cosi.AggregateSig(sig2arr)
vcMsg.M2Aggsigs = m2Sig.Serialize() vcMsg.M2Aggsigs = m2Sig.Serialize()
@ -147,7 +143,7 @@ func (consensus *Consensus) constructNewViewMessage(viewID uint64, priKey *bls.P
marshaledMessage, err := consensus.signAndMarshalConsensusMessage(message, priKey.Pri) marshaledMessage, err := consensus.signAndMarshalConsensusMessage(message, priKey.Pri)
if err != nil { if err != nil {
utils.Logger().Error().Err(err). consensus.getLogger().Err(err).
Msg("[constructNewViewMessage] failed to sign and marshal the new view message") Msg("[constructNewViewMessage] failed to sign and marshal the new view message")
} }
return proto.ConstructConsensusMessage(marshaledMessage) return proto.ConstructConsensusMessage(marshaledMessage)

@ -29,7 +29,7 @@ type NetworkMessage struct {
func (consensus *Consensus) populateMessageFields( func (consensus *Consensus) populateMessageFields(
request *msg_pb.ConsensusRequest, blockHash []byte, request *msg_pb.ConsensusRequest, blockHash []byte,
) *msg_pb.ConsensusRequest { ) *msg_pb.ConsensusRequest {
request.ViewId = consensus.viewID request.ViewId = consensus.GetCurViewID()
request.BlockNum = consensus.blockNum request.BlockNum = consensus.blockNum
request.ShardId = consensus.ShardID request.ShardId = consensus.ShardID
// 32 byte block hash // 32 byte block hash

@ -77,7 +77,7 @@ func TestConstructPreparedMessage(test *testing.T) {
leaderPriKey.Sign(message), leaderPriKey.Sign(message),
common.BytesToHash(consensus.blockHash[:]), common.BytesToHash(consensus.blockHash[:]),
consensus.blockNum, consensus.blockNum,
consensus.viewID, consensus.GetCurViewID(),
) )
if _, err := consensus.Decider.SubmitVote( if _, err := consensus.Decider.SubmitVote(
quorum.Prepare, quorum.Prepare,
@ -85,7 +85,7 @@ func TestConstructPreparedMessage(test *testing.T) {
validatorPriKey.Sign(message), validatorPriKey.Sign(message),
common.BytesToHash(consensus.blockHash[:]), common.BytesToHash(consensus.blockHash[:]),
consensus.blockNum, consensus.blockNum,
consensus.viewID, consensus.GetCurViewID(),
); err != nil { ); err != nil {
test.Log(err) test.Log(err)
} }

@ -0,0 +1,21 @@
package consensus
// GetConsensusPhase returns the current phase of the consensus
func (c *Consensus) GetConsensusPhase() string {
return c.phase.String()
}
// GetConsensusMode returns the current mode of the consensus
func (c *Consensus) GetConsensusMode() string {
return c.current.mode.String()
}
// GetCurViewID returns the current view ID of the consensus
func (c *Consensus) GetCurViewID() uint64 {
return c.current.GetCurViewID()
}
// GetViewChangingID returns the current view changing ID of the consensus
func (c *Consensus) GetViewChangingID() uint64 {
return c.current.GetViewChangingID()
}

@ -110,12 +110,11 @@ func (consensus *Consensus) onPrepare(msg *msg_pb.Message) {
// TODO(audit): make FBFT lookup using map instead of looping through all items. // TODO(audit): make FBFT lookup using map instead of looping through all items.
if !consensus.FBFTLog.HasMatchingViewAnnounce( if !consensus.FBFTLog.HasMatchingViewAnnounce(
consensus.blockNum, consensus.viewID, recvMsg.BlockHash, consensus.blockNum, consensus.GetCurViewID(), recvMsg.BlockHash,
) { ) {
consensus.getLogger().Debug(). consensus.getLogger().Debug().
Uint64("MsgViewID", recvMsg.ViewID). Uint64("MsgViewID", recvMsg.ViewID).
Uint64("MsgBlockNum", recvMsg.BlockNum). Uint64("MsgBlockNum", recvMsg.BlockNum).
Uint64("blockNum", consensus.blockNum).
Msg("[OnPrepare] No Matching Announce message") Msg("[OnPrepare] No Matching Announce message")
} }
@ -288,7 +287,7 @@ func (consensus *Consensus) onCommit(msg *msg_pb.Message) {
//// Write - End //// Write - End
//// Read - Start //// Read - Start
viewID := consensus.viewID viewID := consensus.GetCurViewID()
if consensus.Decider.IsAllSigsCollected() { if consensus.Decider.IsAllSigsCollected() {
go func(viewID uint64) { go func(viewID uint64) {

@ -29,37 +29,73 @@ const MaxViewIDDiff = 100
// State contains current mode and current viewID // State contains current mode and current viewID
type State struct { type State struct {
mode Mode mode Mode
viewID uint64 modeMux sync.RWMutex
mux sync.Mutex
// current view id in normal mode
// it changes per successful consensus
curViewID uint64
cViewMux sync.RWMutex
// view changing id is used during view change mode
// it is the next view id
viewChangingID uint64
viewMux sync.RWMutex
} }
// Mode return the current node mode // Mode return the current node mode
func (pm *State) Mode() Mode { func (pm *State) Mode() Mode {
pm.modeMux.RLock()
defer pm.modeMux.RUnlock()
return pm.mode return pm.mode
} }
// SetMode set the node mode as required // SetMode set the node mode as required
func (pm *State) SetMode(s Mode) { func (pm *State) SetMode(s Mode) {
pm.mux.Lock() pm.modeMux.Lock()
defer pm.mux.Unlock() defer pm.modeMux.Unlock()
pm.mode = s pm.mode = s
} }
// ViewID return the current viewchanging id // GetCurViewID return the current view id
func (pm *State) ViewID() uint64 { func (pm *State) GetCurViewID() uint64 {
return pm.viewID pm.cViewMux.RLock()
defer pm.cViewMux.RUnlock()
return pm.curViewID
}
// SetCurViewID sets the current view id
func (pm *State) SetCurViewID(viewID uint64) {
pm.cViewMux.Lock()
defer pm.cViewMux.Unlock()
pm.curViewID = viewID
}
// GetViewChangingID return the current view changing id
// It is meaningful during view change mode
func (pm *State) GetViewChangingID() uint64 {
pm.viewMux.RLock()
defer pm.viewMux.RUnlock()
return pm.viewChangingID
} }
// SetViewID sets the viewchanging id accordingly // SetViewChangingID set the current view changing id
func (pm *State) SetViewID(viewID uint64) { // It is meaningful during view change mode
pm.mux.Lock() func (pm *State) SetViewChangingID(id uint64) {
defer pm.mux.Unlock() pm.viewMux.Lock()
pm.viewID = viewID defer pm.viewMux.Unlock()
pm.viewChangingID = id
} }
// GetViewID returns the current viewchange viewID // GetViewChangeDuraion return the duration of the current view change
func (pm *State) GetViewID() uint64 { // It increase in the power of difference betweeen view changing ID and current view ID
return pm.viewID func (pm *State) GetViewChangeDuraion() time.Duration {
pm.viewMux.RLock()
pm.cViewMux.RLock()
defer pm.viewMux.RUnlock()
defer pm.cViewMux.RUnlock()
diff := int64(pm.viewChangingID - pm.curViewID)
return time.Duration(diff * diff * int64(viewChangeDuration))
} }
// switchPhase will switch FBFTPhase to nextPhase if the desirePhase equals the nextPhase // switchPhase will switch FBFTPhase to nextPhase if the desirePhase equals the nextPhase
@ -126,13 +162,12 @@ func (consensus *Consensus) startViewChange(viewID uint64) {
consensus.consensusTimeout[timeoutConsensus].Stop() consensus.consensusTimeout[timeoutConsensus].Stop()
consensus.consensusTimeout[timeoutBootstrap].Stop() consensus.consensusTimeout[timeoutBootstrap].Stop()
consensus.current.SetMode(ViewChanging) consensus.current.SetMode(ViewChanging)
consensus.current.SetViewID(viewID) consensus.SetViewChangingID(viewID)
consensus.LeaderPubKey = consensus.GetNextLeaderKey() consensus.LeaderPubKey = consensus.GetNextLeaderKey()
diff := int64(viewID - consensus.viewID) duration := consensus.current.GetViewChangeDuraion()
duration := time.Duration(diff * diff * int64(viewChangeDuration)) consensus.getLogger().Warn().
consensus.getLogger().Info(). Uint64("viewChangingID", consensus.GetViewChangingID()).
Uint64("ViewChangingID", viewID).
Dur("timeoutDuration", duration). Dur("timeoutDuration", duration).
Str("NextLeader", consensus.LeaderPubKey.Bytes.Hex()). Str("NextLeader", consensus.LeaderPubKey.Bytes.Hex()).
Msg("[startViewChange]") Msg("[startViewChange]")
@ -151,9 +186,6 @@ func (consensus *Consensus) startViewChange(viewID uint64) {
consensus.consensusTimeout[timeoutViewChange].SetDuration(duration) consensus.consensusTimeout[timeoutViewChange].SetDuration(duration)
consensus.consensusTimeout[timeoutViewChange].Start() consensus.consensusTimeout[timeoutViewChange].Start()
consensus.getLogger().Info().
Uint64("ViewChangingID", consensus.current.ViewID()).
Msg("[startViewChange] start view change timer")
} }
func (consensus *Consensus) onViewChange(msg *msg_pb.Message) { func (consensus *Consensus) onViewChange(msg *msg_pb.Message) {
@ -182,10 +214,7 @@ func (consensus *Consensus) onViewChange(msg *msg_pb.Message) {
return return
} }
if len(recvMsg.SenderPubkeys) != 1 { // already checked the length of SenderPubkeys in onViewChangeSanityCheck
consensus.getLogger().Error().Msg("[onViewChange] multiple signers in view change message.")
return
}
senderKey := recvMsg.SenderPubkeys[0] senderKey := recvMsg.SenderPubkeys[0]
consensus.vcLock.Lock() consensus.vcLock.Lock()
@ -396,7 +425,7 @@ func (consensus *Consensus) onViewChange(msg *msg_pb.Message) {
if len(consensus.m1Payload) == 0 { if len(consensus.m1Payload) == 0 {
// TODO(Chao): explain why ReadySignal is sent only in this case but not the other case. // TODO(Chao): explain why ReadySignal is sent only in this case but not the other case.
// Make sure the newly proposed block have the correct view ID // Make sure the newly proposed block have the correct view ID
consensus.viewID = recvMsg.ViewID consensus.SetCurViewID(recvMsg.ViewID)
go func() { go func() {
consensus.ReadySignal <- struct{}{} consensus.ReadySignal <- struct{}{}
}() }()
@ -447,7 +476,7 @@ func (consensus *Consensus) onViewChange(msg *msg_pb.Message) {
} }
} }
consensus.current.SetViewID(recvMsg.ViewID) consensus.SetCurViewID(recvMsg.ViewID)
msgToSend := consensus.constructNewViewMessage( msgToSend := consensus.constructNewViewMessage(
recvMsg.ViewID, newLeaderPriKey, recvMsg.ViewID, newLeaderPriKey,
) )
@ -467,18 +496,11 @@ func (consensus *Consensus) onViewChange(msg *msg_pb.Message) {
Msg("could not send out the NEWVIEW message") Msg("could not send out the NEWVIEW message")
} }
consensus.viewID = recvMsg.ViewID consensus.SetCurViewID(recvMsg.ViewID)
consensus.ResetViewChangeState() consensus.ResetViewChangeState()
consensus.consensusTimeout[timeoutViewChange].Stop() consensus.consensusTimeout[timeoutViewChange].Stop()
consensus.consensusTimeout[timeoutConsensus].Start() consensus.consensusTimeout[timeoutConsensus].Start()
consensus.getLogger().Debug(). consensus.getLogger().Info().Str("myKey", newLeaderKey.Bytes.Hex()).Msg("[onViewChange] I am the New Leader")
Uint64("viewChangingID", consensus.current.ViewID()).
Msg("[onViewChange] New Leader Start Consensus Timer and Stop View Change Timer")
consensus.getLogger().Info().
Str("myKey", newLeaderKey.Bytes.Hex()).
Uint64("viewID", consensus.viewID).
Uint64("block", consensus.blockNum).
Msg("[onViewChange] I am the New Leader")
} }
} }
@ -612,8 +634,7 @@ func (consensus *Consensus) onNewView(msg *msg_pb.Message) {
} }
// newView message verified success, override my state // newView message verified success, override my state
consensus.viewID = recvMsg.ViewID consensus.SetCurViewID(recvMsg.ViewID)
consensus.current.SetViewID(recvMsg.ViewID)
consensus.LeaderPubKey = senderKey consensus.LeaderPubKey = senderKey
consensus.ResetViewChangeState() consensus.ResetViewChangeState()

@ -25,15 +25,11 @@ func TestBasicViewChanging(t *testing.T) {
assert.Equal(t, ViewChanging, consensus.current.Mode()) assert.Equal(t, ViewChanging, consensus.current.Mode())
// Change ViewID // Change ViewID
assert.Equal(t, state.viewID, consensus.current.viewID) assert.Equal(t, state.GetViewChangingID(), consensus.current.GetViewChangingID())
assert.Equal(t, state.ViewID(), consensus.current.ViewID())
assert.Equal(t, state.GetViewID(), consensus.current.GetViewID()) // Why are there two methods to retrieve the ViewID? newViewID := consensus.current.GetViewChangingID() + 1
consensus.SetViewIDs(newViewID)
newViewID := consensus.current.ViewID() + 1 assert.Equal(t, newViewID, consensus.current.GetViewChangingID())
consensus.current.SetViewID(newViewID)
assert.Equal(t, newViewID, consensus.current.viewID)
assert.Equal(t, newViewID, consensus.current.ViewID())
assert.Equal(t, newViewID, consensus.current.GetViewID())
} }
func TestPhaseSwitching(t *testing.T) { func TestPhaseSwitching(t *testing.T) {

@ -19,7 +19,7 @@ require (
github.com/fjl/memsize v0.0.0-20180929194037-2a09253e352a // indirect github.com/fjl/memsize v0.0.0-20180929194037-2a09253e352a // indirect
github.com/garslo/gogen v0.0.0-20170307003452-d6ebae628c7c // indirect github.com/garslo/gogen v0.0.0-20170307003452-d6ebae628c7c // indirect
github.com/golang/mock v1.4.0 github.com/golang/mock v1.4.0
github.com/golang/protobuf v1.4.0 github.com/golang/protobuf v1.4.2
github.com/golangci/golangci-lint v1.22.2 github.com/golangci/golangci-lint v1.22.2
github.com/gorilla/mux v1.7.4 github.com/gorilla/mux v1.7.4
github.com/gorilla/websocket v1.4.2 // indirect github.com/gorilla/websocket v1.4.2 // indirect

@ -92,6 +92,13 @@ type NodeAPI interface {
ListPeer(topic string) []peer.ID ListPeer(topic string) []peer.ID
ListTopic() []string ListTopic() []string
ListBlockedPeer() []peer.ID ListBlockedPeer() []peer.ID
// debug API
GetConsensusMode() string
GetConsensusPhase() string
GetConsensusViewChangingID() uint64
GetConsensusCurViewID() uint64
ShutDown()
} }
// New creates a new Harmony object (including the // New creates a new Harmony object (including the

@ -106,3 +106,23 @@ func (node *Node) APIs(harmony *hmy.Harmony) []rpc.API {
}, },
} }
} }
// GetConsensusMode returns the current consensus mode
func (node *Node) GetConsensusMode() string {
return node.Consensus.GetConsensusMode()
}
// GetConsensusPhase returns the current consensus phase
func (node *Node) GetConsensusPhase() string {
return node.Consensus.GetConsensusPhase()
}
// GetConsensusViewChangingID returns the view changing ID
func (node *Node) GetConsensusViewChangingID() uint64 {
return node.Consensus.GetViewChangingID()
}
// GetConsensusCurViewID returns the current view ID
func (node *Node) GetConsensusCurViewID() uint64 {
return node.Consensus.GetCurViewID()
}

@ -456,6 +456,12 @@ func (node *Node) validateShardBoundMessage(
case msg_pb.MessageType_PREPARE, msg_pb.MessageType_COMMIT: case msg_pb.MessageType_PREPARE, msg_pb.MessageType_COMMIT:
return nil, nil, true, nil return nil, nil, true, nil
} }
} else {
// ignore newview message if the node is not in viewchanging mode
switch m.Type {
case msg_pb.MessageType_NEWVIEW:
return nil, nil, true, nil
}
} }
// ignore message not intended for leader, but still forward them to the network // ignore message not intended for leader, but still forward them to the network

@ -232,7 +232,7 @@ func (node *Node) proposeNewBlock() (*types.Block, error) {
} }
return node.Worker.FinalizeNewBlock( return node.Worker.FinalizeNewBlock(
sig, mask, node.Consensus.GetViewID(), sig, mask, node.Consensus.GetCurViewID(),
coinbase, crossLinksToPropose, shardState, coinbase, crossLinksToPropose, shardState,
) )
} }

@ -38,3 +38,31 @@ func (*PrivateDebugService) SetLogVerbosity(ctx context.Context, level int) (map
utils.SetLogVerbosity(verbosity) utils.SetLogVerbosity(verbosity)
return map[string]interface{}{"verbosity": verbosity.String()}, nil return map[string]interface{}{"verbosity": verbosity.String()}, nil
} }
// ConsensusViewChangingID return the current view changing ID to RPC
func (s *PrivateDebugService) ConsensusViewChangingID(
ctx context.Context,
) uint64 {
return s.hmy.NodeAPI.GetConsensusViewChangingID()
}
// ConsensusCurViewID return the current view ID to RPC
func (s *PrivateDebugService) ConsensusCurViewID(
ctx context.Context,
) uint64 {
return s.hmy.NodeAPI.GetConsensusCurViewID()
}
// GetConsensusMode return the current consensus mode
func (s *PrivateDebugService) GetConsensusMode(
ctx context.Context,
) string {
return s.hmy.NodeAPI.GetConsensusMode()
}
// GetConsensusPhase return the current consensus mode
func (s *PrivateDebugService) GetConsensusPhase(
ctx context.Context,
) string {
return s.hmy.NodeAPI.GetConsensusPhase()
}

@ -12,4 +12,4 @@ esac
sed -n 's/^ _ "\([^"]*\)"$/\1/p' "${progdir}/../tools/tools.go" | \ sed -n 's/^ _ "\([^"]*\)"$/\1/p' "${progdir}/../tools/tools.go" | \
xargs "${progdir}/goget.sh" xargs "${progdir}/goget.sh"
"${progdir}/install_protoc.sh" -V 3.6.1 "${progdir}/install_protoc.sh" -V 3.12.3

@ -58,4 +58,5 @@ curl -s -S -L -o "${filename}" "${url}"
echo "Downloaded as ${filename}; unzipping into ${destdir}..." echo "Downloaded as ${filename}; unzipping into ${destdir}..."
sudo unzip -o -d "${destdir}" "${filename}" sudo unzip -o -d "${destdir}" "${filename}"
echo "protoc v${version} has been installed in ${destdir}." echo "protoc v${version} has been installed in ${destdir}."
sudo chmod +x "${destdir}/bin/protoc"
exit 0 exit 0

Loading…
Cancel
Save