From a2d77cbe4e02c4b8843a3cb7301f6c9fd23523ae Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 26 Apr 2018 23:11:20 -0400 Subject: [PATCH 1/6] add MarshalJSON methods to fix dump_consensus_state --- consensus/types/height_vote_set.go | 24 ++++++++++++++++++++++++ types/part_set.go | 17 +++++++++++++++++ types/vote_set.go | 20 ++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/consensus/types/height_vote_set.go b/consensus/types/height_vote_set.go index a155bce08..f65f365b8 100644 --- a/consensus/types/height_vote_set.go +++ b/consensus/types/height_vote_set.go @@ -207,6 +207,30 @@ func (hvs *HeightVoteSet) StringIndented(indent string) string { indent) } +type roundVoteBitArrays struct { + Round int `json:"round"` + Prevotes *cmn.BitArray `json:"prevotes"` + Precommits *cmn.BitArray `json:"precommits"` +} + +func (hvs *HeightVoteSet) MarshalJSON() ([]byte, error) { + hvs.mtx.Lock() + defer hvs.mtx.Unlock() + totalRounds := hvs.round + 1 + roundsVotes := make([]roundVoteBitArrays, totalRounds) + // rounds 0 ~ hvs.round inclusive + for round := 0; round < totalRounds; round++ { + roundsVotes[round] = roundVoteBitArrays{ + Round: round, + Prevotes: hvs.roundVoteSets[round].Prevotes.BitArray(), + Precommits: hvs.roundVoteSets[round].Precommits.BitArray(), + } + } + // TODO: all other peer catchup rounds + + return cdc.MarshalJSON(roundsVotes) +} + // If a peer claims that it has 2/3 majority for given blockKey, call this. // NOTE: if there are too many peers, or too much peer churn, // this can cause memory issues. diff --git a/types/part_set.go b/types/part_set.go index 749943291..e4f2b9e97 100644 --- a/types/part_set.go +++ b/types/part_set.go @@ -264,3 +264,20 @@ func (ps *PartSet) StringShort() string { defer ps.mtx.Unlock() return fmt.Sprintf("(%v of %v)", ps.Count(), ps.Total()) } + +func (ps *PartSet) MarshalJSON() ([]byte, error) { + if ps == nil { + return []byte("nil-PartSet"), nil + } + + ps.mtx.Lock() + defer ps.mtx.Unlock() + + return cdc.MarshalJSON(struct { + CountTotal string `json:"count/total"` + PartsBitArray *cmn.BitArray `json:"parts_bit_array"` + }{ + fmt.Sprintf("%d/%d", ps.Count(), ps.Total()), + ps.partsBitArray.Copy(), + }) +} diff --git a/types/vote_set.go b/types/vote_set.go index e255488d6..07ef60ec6 100644 --- a/types/vote_set.go +++ b/types/vote_set.go @@ -445,6 +445,26 @@ func (voteSet *VoteSet) StringIndented(indent string) string { indent) } +// Marshal the VoteSet to JSON. Same as String(), just in JSON, +// and without the height/round/type_ (since its already included in the votes). +func (voteSet *VoteSet) MarshalJSON() ([]byte, error) { + voteStrings := make([]string, len(voteSet.votes)) + for i, vote := range voteSet.votes { + if vote == nil { + voteStrings[i] = "nil-Vote" + } else { + voteStrings[i] = vote.String() + } + } + return cdc.MarshalJSON(struct { + Votes []string `json:"votes"` + VotesBitArray *cmn.BitArray `json:"votes_bit_array"` + PeerMaj23s map[P2PID]BlockID `json:"peer_maj_23s"` + }{ + voteStrings, voteSet.votesBitArray, voteSet.peerMaj23s, + }) +} + func (voteSet *VoteSet) StringShort() string { if voteSet == nil { return "nil-VoteSet" From 47e4d64973fe4efb201c17a2dad2cea4f20efa13 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 26 Apr 2018 23:13:56 -0400 Subject: [PATCH 2/6] add validator address to /status --- rpc/core/status.go | 16 ++++++++++------ rpc/core/types/responses.go | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/rpc/core/status.go b/rpc/core/status.go index 9bdf9dd64..32647add5 100644 --- a/rpc/core/status.go +++ b/rpc/core/status.go @@ -79,6 +79,11 @@ func Status() (*ctypes.ResultStatus, error) { latestBlockTime := time.Unix(0, latestBlockTimeNano) + var votingPower int64 + if val := validatorAtHeight(latestHeight); val != nil { + votingPower = val.VotingPower + } + result := &ctypes.ResultStatus{ NodeInfo: p2pSwitch.NodeInfo(), SyncInfo: ctypes.SyncInfo{ @@ -88,12 +93,11 @@ func Status() (*ctypes.ResultStatus, error) { LatestBlockTime: latestBlockTime, Syncing: consensusReactor.FastSync(), }, - ValidatorInfo: ctypes.ValidatorInfo{PubKey: pubKey}, - } - - // add ValidatorStatus if node is a validator - if val := validatorAtHeight(latestHeight); val != nil { - result.ValidatorInfo.VotingPower = val.VotingPower + ValidatorInfo: ctypes.ValidatorInfo{ + Address: pubKey.Address(), + PubKey: pubKey, + VotingPower: votingPower, + }, } return result, nil diff --git a/rpc/core/types/responses.go b/rpc/core/types/responses.go index 82bfceaa7..ef4d72614 100644 --- a/rpc/core/types/responses.go +++ b/rpc/core/types/responses.go @@ -63,6 +63,7 @@ type SyncInfo struct { } type ValidatorInfo struct { + Address cmn.HexBytes `json:"address"` PubKey crypto.PubKey `json:"pub_key"` VotingPower int64 `json:"voting_power"` } From 94e823cc91c4d0b9103f1086ede772f14e33a1ce Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 26 Apr 2018 23:40:29 -0400 Subject: [PATCH 3/6] p2p: NodeInfo.Channels is HexBytes --- p2p/node_info.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/p2p/node_info.go b/p2p/node_info.go index 930f9bfea..e46236188 100644 --- a/p2p/node_info.go +++ b/p2p/node_info.go @@ -3,6 +3,8 @@ package p2p import ( "fmt" "strings" + + cmn "github.com/tendermint/tmlibs/common" ) const ( @@ -10,6 +12,7 @@ const ( maxNumChannels = 16 // plenty of room for upgrades, for now ) +// Max size of the NodeInfo struct func MaxNodeInfoSize() int { return maxNodeInfoSize } @@ -21,10 +24,11 @@ type NodeInfo struct { ID ID `json:"id"` // authenticated identifier ListenAddr string `json:"listen_addr"` // accepting incoming - // Check compatibility - Network string `json:"network"` // network/chain ID - Version string `json:"version"` // major.minor.revision - Channels []byte `json:"channels"` // channels this node knows about + // Check compatibility. + // Channels are HexBytes so easier to read as JSON + Network string `json:"network"` // network/chain ID + Version string `json:"version"` // major.minor.revision + Channels cmn.HexBytes `json:"channels"` // channels this node knows about // Sanitize Moniker string `json:"moniker"` // arbitrary moniker From 593a785ae278c525b9879ef4579bf2fd3fe269f8 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 26 Apr 2018 23:49:48 -0400 Subject: [PATCH 4/6] set NodeInfo on switch before starting RPC server should fix #1199 --- node/node.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/node/node.go b/node/node.go index 976066964..d3d8968de 100644 --- a/node/node.go +++ b/node/node.go @@ -382,16 +382,6 @@ func (n *Node) OnStart() error { return err } - // Run the RPC server first - // so we can eg. receive txs for the first block - if n.config.RPC.ListenAddress != "" { - listeners, err := n.startRPC() - if err != nil { - return err - } - n.rpcListeners = listeners - } - // Create & add listener protocol, address := cmn.ProtocolAndAddress(n.config.P2P.ListenAddress) l := p2p.NewDefaultListener(protocol, address, n.config.P2P.SkipUPNP, n.Logger.With("module", "p2p")) @@ -412,6 +402,16 @@ func (n *Node) OnStart() error { // Add ourselves to addrbook to prevent dialing ourselves n.addrBook.AddOurAddress(nodeInfo.NetAddress()) + // Run the RPC server first + // so we can eg. receive txs for the first block + if n.config.RPC.ListenAddress != "" { + listeners, err := n.startRPC() + if err != nil { + return err + } + n.rpcListeners = listeners + } + // Start the switch err = n.sw.Start() if err != nil { From f67c5a9e7b914ed7bd13a0a8f10822ce57ec4bbb Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Apr 2018 10:00:34 -0400 Subject: [PATCH 5/6] forgot wire.go file --- consensus/types/wire.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 consensus/types/wire.go diff --git a/consensus/types/wire.go b/consensus/types/wire.go new file mode 100644 index 000000000..bd5c4497d --- /dev/null +++ b/consensus/types/wire.go @@ -0,0 +1,12 @@ +package types + +import ( + "github.com/tendermint/go-amino" + "github.com/tendermint/go-crypto" +) + +var cdc = amino.NewCodec() + +func init() { + crypto.RegisterAmino(cdc) +} From c45ba2967af8232d0ce7897231e47c607acb758b Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Apr 2018 10:29:05 -0400 Subject: [PATCH 6/6] fixes from review --- node/node.go | 4 ++-- types/part_set.go | 4 ++-- types/vote_set.go | 8 +++++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/node/node.go b/node/node.go index d3d8968de..205e672f3 100644 --- a/node/node.go +++ b/node/node.go @@ -402,7 +402,7 @@ func (n *Node) OnStart() error { // Add ourselves to addrbook to prevent dialing ourselves n.addrBook.AddOurAddress(nodeInfo.NetAddress()) - // Run the RPC server first + // Start the RPC server before the P2P server // so we can eg. receive txs for the first block if n.config.RPC.ListenAddress != "" { listeners, err := n.startRPC() @@ -412,7 +412,7 @@ func (n *Node) OnStart() error { n.rpcListeners = listeners } - // Start the switch + // Start the switch (the P2P server). err = n.sw.Start() if err != nil { return err diff --git a/types/part_set.go b/types/part_set.go index e4f2b9e97..cad3a03fe 100644 --- a/types/part_set.go +++ b/types/part_set.go @@ -267,7 +267,7 @@ func (ps *PartSet) StringShort() string { func (ps *PartSet) MarshalJSON() ([]byte, error) { if ps == nil { - return []byte("nil-PartSet"), nil + return []byte("{}"), nil } ps.mtx.Lock() @@ -278,6 +278,6 @@ func (ps *PartSet) MarshalJSON() ([]byte, error) { PartsBitArray *cmn.BitArray `json:"parts_bit_array"` }{ fmt.Sprintf("%d/%d", ps.Count(), ps.Total()), - ps.partsBitArray.Copy(), + ps.partsBitArray, }) } diff --git a/types/vote_set.go b/types/vote_set.go index 07ef60ec6..c5c72d435 100644 --- a/types/vote_set.go +++ b/types/vote_set.go @@ -56,9 +56,9 @@ type VoteSet struct { height int64 round int type_ byte + valSet *ValidatorSet mtx sync.Mutex - valSet *ValidatorSet votesBitArray *cmn.BitArray votes []*Vote // Primary votes to share sum int64 // Sum of voting power for seen votes, discounting conflicts @@ -399,6 +399,8 @@ func (voteSet *VoteSet) HasTwoThirdsAny() bool { } func (voteSet *VoteSet) HasAll() bool { + voteSet.mtx.Lock() + defer voteSet.mtx.Unlock() return voteSet.sum == voteSet.valSet.TotalVotingPower() } @@ -424,6 +426,8 @@ func (voteSet *VoteSet) String() string { } func (voteSet *VoteSet) StringIndented(indent string) string { + voteSet.mtx.Lock() + defer voteSet.mtx.Unlock() voteStrings := make([]string, len(voteSet.votes)) for i, vote := range voteSet.votes { if vote == nil { @@ -448,6 +452,8 @@ func (voteSet *VoteSet) StringIndented(indent string) string { // Marshal the VoteSet to JSON. Same as String(), just in JSON, // and without the height/round/type_ (since its already included in the votes). func (voteSet *VoteSet) MarshalJSON() ([]byte, error) { + voteSet.mtx.Lock() + defer voteSet.mtx.Unlock() voteStrings := make([]string, len(voteSet.votes)) for i, vote := range voteSet.votes { if vote == nil {