func (prot *Protocol) propagateMessage(payload []byte, h types.Hash12, nextProt string, exclude p2pcrypto.PublicKey) {
	prot.peersMutex.RLock()
	peers := make([]p2pcrypto.PublicKey, 0, len(prot.peers))
	for p := range prot.peers {
		peers = append(peers, p)
	}
	prot.peersMutex.RUnlock()
	var wg sync.WaitGroup
peerLoop:
	for _, p := range peers {
		if exclude == p {
			continue peerLoop
		}
		wg.Add(1)
		go func(pubkey p2pcrypto.PublicKey) {
			err := prot.net.SendMessage(pubkey, nextProt, payload)
			if err != nil {
				prot.With().Warning("Failed sending", log.String("protocol", nextProt), h.Field("hash"), log.String("to", pubkey.String()), log.Err(err))
			}
			wg.Done()
		}(p)
	}
	wg.Wait()
}
send a message to all the peers.
package gossip
import (
	"sync"
	"github.com/libonomy/libonomy-p2p/common/types"
	"github.com/libonomy/libonomy-p2p/common/util"
	"github.com/libonomy/libonomy-p2p/log"
	"github.com/libonomy/libonomy-p2p/p2p/config"
	"github.com/libonomy/libonomy-p2p/p2p/metrics"
	"github.com/libonomy/libonomy-p2p/p2p/p2pcrypto"
	"github.com/libonomy/libonomy-p2p/p2p/service"
	"github.com/libonomy/libonomy-p2p/priorityq"
)
const oldMessageCacheSize = 10000
const propagateHandleBufferSize = 5000  
type baseNetwork interface {
	SendMessage(peerPubkey p2pcrypto.PublicKey, protocol string, payload []byte) error
	SubscribePeerEvents() (conn chan p2pcrypto.PublicKey, disc chan p2pcrypto.PublicKey)
	ProcessGossipProtocolMessage(sender p2pcrypto.PublicKey, protocol string, data service.Data, validationCompletedChan chan service.MessageValidation) error
}
type prioQ interface {
	Write(prio priorityq.Priority, m interface{}) error
	Read() (interface{}, error)
	Close()
}
type Protocol struct {
	log.Log
	config          config.SwarmConfig
	net             baseNetwork
	localNodePubkey p2pcrypto.PublicKey
	peers      map[p2pcrypto.PublicKey]*peer
	peersMutex sync.RWMutex
	shutdown chan struct{}
	oldMessageQ *types.DoubleCache
	propagateQ chan service.MessageValidation
	pq         prioQ
	priorities map[string]priorityq.Priority
}
func NewProtocol(config config.SwarmConfig, base baseNetwork, localNodePubkey p2pcrypto.PublicKey, log2 log.Log) *Protocol {
	return &Protocol{
		Log:             log2,
		config:          config,
		net:             base,
		localNodePubkey: localNodePubkey,
		peers:           make(map[p2pcrypto.PublicKey]*peer),
		shutdown:        make(chan struct{}),
		oldMessageQ:     types.NewDoubleCache(oldMessageCacheSize),  
		propagateQ:      make(chan service.MessageValidation, propagateHandleBufferSize),
		pq:              priorityq.New(propagateHandleBufferSize),
		priorities:      make(map[string]priorityq.Priority),
	}
}
type sender interface {
	SendMessage(peerPubkey p2pcrypto.PublicKey, protocol string, payload []byte) error
}
type peer struct {
	log.Log
	pubkey p2pcrypto.PublicKey
	net    sender
}
func newPeer(net sender, pubkey p2pcrypto.PublicKey, log log.Log) *peer {
	return &peer{
		log,
		pubkey,
		net,
	}
}
func (prot *Protocol) Close() {
	close(prot.shutdown)
}
func (prot *Protocol) markMessageAsOld(h types.Hash12) bool {
	ok := prot.oldMessageQ.GetOrInsert(h)
	return ok
}