func (info NodeInfo) CompatibleWith(other NodeInfo) error {
	iMajor, _, _, iErr := splitVersion(info.Version)
	oMajor, _, _, oErr := splitVersion(other.Version)
	if iErr != nil {
		return iErr
	}
	if oErr != nil {
		return oErr
	}
	if iMajor != oMajor {
		return fmt.Errorf("Peer is on a different major version. Got %v, expected %v", oMajor, iMajor)
	}
	if info.Network != other.Network {
		return fmt.Errorf("Peer is on a different network. Got %v, expected %v", other.Network, info.Network)
	}
	if len(info.Channels) == 0 {
		return nil
	}
	found := false
OUTER_LOOP:
	for _, ch1 := range info.Channels {
		for _, ch2 := range other.Channels {
			if ch1 == ch2 {
				found = true
				break OUTER_LOOP  
			}
		}
	}
	if !found {
		return fmt.Errorf("Peer has no common channels. Our channels: %v ; Peer channels: %v", info.Channels, other.Channels)
	}
	return nil
}
CompatibleWith checks if two NodeInfo are compatible with eachother.
CONTRACT: two nodes are compatible if the major version matches and network match
and they have at least one channel in common.
package p2p
import (
	"fmt"
	"strings"
	cmn "github.com/tendermint/tendermint/libs/common"
)
const (
	maxNodeInfoSize = 10240  
	maxNumChannels  = 16     
)
func MaxNodeInfoSize() int {
	return maxNodeInfoSize
}
type NodeInfo struct {
	ID         ID     `json:"id"`           
	ListenAddr string `json:"listen_addr"`  
	Network  string       `json:"network"`   
	Version  string       `json:"version"`   
	Channels cmn.HexBytes `json:"channels"`  
	Moniker string   `json:"moniker"`  
	Other   []string `json:"other"`    
}
func (info NodeInfo) Validate() error {
	if len(info.Channels) > maxNumChannels {
		return fmt.Errorf("info.Channels is too long (%v). Max is %v", len(info.Channels), maxNumChannels)
	}
	if !cmn.IsASCIIText(info.Moniker) || cmn.ASCIITrim(info.Moniker) == "" {
		return fmt.Errorf("info.Moniker must be valid non-empty ASCII text without tabs, but got %v.", info.Moniker)
	}
	for i, s := range info.Other {
		if !cmn.IsASCIIText(s) || cmn.ASCIITrim(s) == "" {
			return fmt.Errorf("info.Other[%v] must be valid non-empty ASCII text without tabs, but got %v.", i, s)
		}
	}
	channels := make(map[byte]struct{})
	for _, ch := range info.Channels {
		_, ok := channels[ch]
		if ok {
			return fmt.Errorf("info.Channels contains duplicate channel id %v", ch)
		}
		channels[ch] = struct{}{}
	}
	_, err := NewNetAddressString(IDAddressString(info.ID, info.ListenAddr))
	return err
}