From 5dbe29ee50ca9db4b82bbaf2d15777162fa43743 Mon Sep 17 00:00:00 2001 From: YACOVM Date: Sun, 12 Feb 2017 01:26:19 +0200 Subject: [PATCH] [FAB-2198] Introduce envelopes to gossip message The current gossip implementation uses proto.Marshal and then signs over this output both in the signer and the verifier, which might be dangerous because protobuf marshalling isn't guaranteed to be deterministic. This is the first commit in the series that introduces an envelope message to the GossipMessage, and does some refactoring and preperation for next commit(s) that'll change the stream definition, the signing, and entity-storage related structures. The refactoring basically entails moving the ReceivedMessage from comm to proto, as part of the extensions to the gossip proto types. Signed-off-by: Yacov Manevich Change-Id: Ifcedaa87bcf45376a4569ed80b7e7d1b76c87883 --- gossip/comm/comm.go | 19 +-- gossip/comm/comm_impl.go | 8 +- gossip/comm/comm_test.go | 16 +- gossip/comm/mock/mock_comm.go | 14 +- gossip/comm/mock/mock_comm_test.go | 4 +- gossip/comm/msg.go | 6 + gossip/election/adapter.go | 3 +- gossip/election/adapter_test.go | 3 +- gossip/gossip/certstore.go | 5 +- gossip/gossip/certstore_test.go | 18 ++- gossip/gossip/channel/channel.go | 6 +- gossip/gossip/channel/channel_test.go | 6 + gossip/gossip/gossip.go | 2 +- gossip/gossip/gossip_impl.go | 16 +- gossip/gossip/pull/pullstore.go | 10 +- gossip/gossip/pull/pullstore_test.go | 14 +- gossip/state/state.go | 10 +- protos/gossip/extensions.go | 23 +++ protos/gossip/message.pb.go | 219 ++++++++++++++------------ protos/gossip/message.proto | 6 + 20 files changed, 232 insertions(+), 176 deletions(-) diff --git a/gossip/comm/comm.go b/gossip/comm/comm.go index 3603f2f78a6..b6664f84139 100644 --- a/gossip/comm/comm.go +++ b/gossip/comm/comm.go @@ -38,7 +38,7 @@ type Comm interface { // Accept returns a dedicated read-only channel for messages sent by other nodes that match a certain predicate. // Each message from the channel can be used to send a reply back to the sender - Accept(common.MessageAcceptor) <-chan ReceivedMessage + Accept(common.MessageAcceptor) <-chan proto.ReceivedMessage // PresumedDead returns a read-only channel for node endpoints that are suspected to be offline PresumedDead() <-chan common.PKIidType @@ -63,20 +63,3 @@ type RemotePeer struct { func (p *RemotePeer) String() string { return fmt.Sprintf("%s, PKIid:%v", p.Endpoint, p.PKIID) } - -// ReceivedMessage is a GossipMessage wrapper that -// enables the user to send a message to the origin from which -// the ReceivedMessage was sent from. -// It also allows to know the identity of the sender -type ReceivedMessage interface { - - // Respond sends a GossipMessage to the origin from which this ReceivedMessage was sent from - Respond(msg *proto.GossipMessage) - - // GetGossipMessage returns the underlying GossipMessage - GetGossipMessage() *proto.GossipMessage - - // GetPKIID returns the PKI-ID of the remote peer - // that sent the message - GetPKIID() common.PKIidType -} diff --git a/gossip/comm/comm_impl.go b/gossip/comm/comm_impl.go index 48415fc878c..b91e492c3df 100644 --- a/gossip/comm/comm_impl.go +++ b/gossip/comm/comm_impl.go @@ -98,7 +98,7 @@ func NewCommInstanceWithServer(port int, idMapper identity.Mapper, peerIdentity deadEndpoints: make(chan common.PKIidType, 100), stopping: int32(0), exitChan: make(chan struct{}, 1), - subscriptions: make([]chan ReceivedMessage, 0), + subscriptions: make([]chan proto.ReceivedMessage, 0), blackListedPKIIDs: make([]common.PKIidType, 0), } commInst.connStore = newConnStore(commInst, commInst.logger) @@ -154,7 +154,7 @@ type commImpl struct { exitChan chan struct{} stopping int32 stopWG sync.WaitGroup - subscriptions []chan ReceivedMessage + subscriptions []chan proto.ReceivedMessage blackListedPKIIDs []common.PKIidType } @@ -290,9 +290,9 @@ func (c *commImpl) Probe(remotePeer *RemotePeer) error { return err } -func (c *commImpl) Accept(acceptor common.MessageAcceptor) <-chan ReceivedMessage { +func (c *commImpl) Accept(acceptor common.MessageAcceptor) <-chan proto.ReceivedMessage { genericChan := c.msgPublisher.AddChannel(acceptor) - specificChan := make(chan ReceivedMessage, 10) + specificChan := make(chan proto.ReceivedMessage, 10) if c.isStopping() { c.logger.Warning("Accept() called but comm module is stopping, returning empty channel") diff --git a/gossip/comm/comm_test.go b/gossip/comm/comm_test.go index 47daa18206c..55131f8c5b3 100644 --- a/gossip/comm/comm_test.go +++ b/gossip/comm/comm_test.go @@ -94,7 +94,7 @@ func newCommInstance(port int, sec api.MessageCryptoService) (Comm, error) { return inst, err } -func handshaker(endpoint string, comm Comm, t *testing.T, sigMutator func([]byte) []byte, pkiIDmutator func([]byte) []byte) <-chan ReceivedMessage { +func handshaker(endpoint string, comm Comm, t *testing.T, sigMutator func([]byte) []byte, pkiIDmutator func([]byte) []byte) <-chan proto.ReceivedMessage { c := &commImpl{} err := generateCertificates("key.pem", "cert.pem") defer os.Remove("cert.pem") @@ -189,7 +189,7 @@ func TestBasic(t *testing.T) { m1 := comm1.Accept(acceptAll) m2 := comm2.Accept(acceptAll) out := make(chan uint64, 2) - reader := func(ch <-chan ReceivedMessage) { + reader := func(ch <-chan proto.ReceivedMessage) { m := <-ch out <- m.GetGossipMessage().Nonce } @@ -228,7 +228,7 @@ func TestBlackListPKIid(t *testing.T) { defer comm3.Stop() defer comm4.Stop() - reader := func(instance string, out chan uint64, in <-chan ReceivedMessage) { + reader := func(instance string, out chan uint64, in <-chan proto.ReceivedMessage) { for { msg := <-in if msg == nil { @@ -328,7 +328,7 @@ func TestResponses(t *testing.T) { defer comm1.Stop() defer comm2.Stop() - nonceIncrememter := func(msg ReceivedMessage) ReceivedMessage { + nonceIncrememter := func(msg proto.ReceivedMessage) proto.ReceivedMessage { msg.GetGossipMessage().Nonce++ return msg } @@ -365,11 +365,11 @@ func TestAccept(t *testing.T) { comm2, _ := newCommInstance(7612, naiveSec) evenNONCESelector := func(m interface{}) bool { - return m.(ReceivedMessage).GetGossipMessage().Nonce%2 == 0 + return m.(proto.ReceivedMessage).GetGossipMessage().Nonce%2 == 0 } oddNONCESelector := func(m interface{}) bool { - return m.(ReceivedMessage).GetGossipMessage().Nonce%2 != 0 + return m.(proto.ReceivedMessage).GetGossipMessage().Nonce%2 != 0 } evenNONCES := comm1.Accept(evenNONCESelector) @@ -381,7 +381,7 @@ func TestAccept(t *testing.T) { out := make(chan uint64, defRecvBuffSize) sem := make(chan struct{}, 0) - readIntoSlice := func(a *[]uint64, ch <-chan ReceivedMessage) { + readIntoSlice := func(a *[]uint64, ch <-chan proto.ReceivedMessage) { for m := range ch { *a = append(*a, m.GetGossipMessage().Nonce) out <- m.GetGossipMessage().Nonce @@ -422,7 +422,7 @@ func TestReConnections(t *testing.T) { comm1, _ := newCommInstance(3611, naiveSec) comm2, _ := newCommInstance(3612, naiveSec) - reader := func(out chan uint64, in <-chan ReceivedMessage) { + reader := func(out chan uint64, in <-chan proto.ReceivedMessage) { for { msg := <-in if msg == nil { diff --git a/gossip/comm/mock/mock_comm.go b/gossip/comm/mock/mock_comm.go index c9b037786ef..8afdec0e2b9 100644 --- a/gossip/comm/mock/mock_comm.go +++ b/gossip/comm/mock/mock_comm.go @@ -46,7 +46,7 @@ type packetMock struct { type channelMock struct { accept common.MessageAcceptor - channel chan comm.ReceivedMessage + channel chan proto.ReceivedMessage } type commMock struct { @@ -91,11 +91,19 @@ func (packet *packetMock) Respond(msg *proto.GossipMessage) { } } +// GetSourceMessage Returns the SignedGossipMessage the ReceivedMessage was +// constructed with +func (packet *packetMock) GetSourceMessage() *proto.SignedGossipMessage { + return nil +} + // GetGossipMessage returns the underlying GossipMessage func (packet *packetMock) GetGossipMessage() *proto.GossipMessage { return packet.msg.(*proto.GossipMessage) } +// GetPKIID returns the PKI-ID of the remote peer +// that sent the message func (packet *packetMock) GetPKIID() common.PKIidType { return nil } @@ -151,8 +159,8 @@ func (mock *commMock) Probe(peer *comm.RemotePeer) error { // Accept returns a dedicated read-only channel for messages sent by other nodes that match a certain predicate. // Each message from the channel can be used to send a reply back to the sender -func (mock *commMock) Accept(accept common.MessageAcceptor) <-chan comm.ReceivedMessage { - ch := make(chan comm.ReceivedMessage) +func (mock *commMock) Accept(accept common.MessageAcceptor) <-chan proto.ReceivedMessage { + ch := make(chan proto.ReceivedMessage) mock.acceptors = append(mock.acceptors, &channelMock{accept, ch}) return ch } diff --git a/gossip/comm/mock/mock_comm_test.go b/gossip/comm/mock/mock_comm_test.go index 7d2d85b0742..84102fe5ff5 100644 --- a/gossip/comm/mock/mock_comm_test.go +++ b/gossip/comm/mock/mock_comm_test.go @@ -37,8 +37,8 @@ func TestMockComm(t *testing.T) { defer comm1.Stop() msgCh := comm1.Accept(func(message interface{}) bool { - return message.(comm.ReceivedMessage).GetGossipMessage().GetStateRequest() != nil || - message.(comm.ReceivedMessage).GetGossipMessage().GetStateResponse() != nil + return message.(proto.ReceivedMessage).GetGossipMessage().GetStateRequest() != nil || + message.(proto.ReceivedMessage).GetGossipMessage().GetStateResponse() != nil }) comm2 := NewCommMock(second.endpoint, members) diff --git a/gossip/comm/msg.go b/gossip/comm/msg.go index f52b797e41d..36965d86b8e 100644 --- a/gossip/comm/msg.go +++ b/gossip/comm/msg.go @@ -30,6 +30,12 @@ type ReceivedMessageImpl struct { conn *connection } +// GetSourceMessage Returns the SignedGossipMessage the ReceivedMessage was +// constructed with +func (m *ReceivedMessageImpl) GetSourceMessage() *proto.SignedGossipMessage { + return nil +} + // Respond sends a msg to the source that sent the ReceivedMessageImpl func (m *ReceivedMessageImpl) Respond(msg *proto.GossipMessage) { m.conn.send(msg, func(e error) {}) diff --git a/gossip/election/adapter.go b/gossip/election/adapter.go index 7f563ea2362..32a54842c1c 100644 --- a/gossip/election/adapter.go +++ b/gossip/election/adapter.go @@ -22,7 +22,6 @@ import ( "time" "github.com/hyperledger/fabric/gossip/api" - "github.com/hyperledger/fabric/gossip/comm" "github.com/hyperledger/fabric/gossip/common" "github.com/hyperledger/fabric/gossip/discovery" proto "github.com/hyperledger/fabric/protos/gossip" @@ -61,7 +60,7 @@ type gossip interface { // If passThrough is false, the messages are processed by the gossip layer beforehand. // If passThrough is true, the gossip layer doesn't intervene and the messages // can be used to send a reply back to the sender - Accept(acceptor common.MessageAcceptor, passThrough bool) (<-chan *proto.GossipMessage, <-chan comm.ReceivedMessage) + Accept(acceptor common.MessageAcceptor, passThrough bool) (<-chan *proto.GossipMessage, <-chan proto.ReceivedMessage) // Gossip sends a message to other peers to the network Gossip(msg *proto.GossipMessage) diff --git a/gossip/election/adapter_test.go b/gossip/election/adapter_test.go index b2aa4bfc41c..7d501e06176 100644 --- a/gossip/election/adapter_test.go +++ b/gossip/election/adapter_test.go @@ -24,7 +24,6 @@ import ( "time" "github.com/hyperledger/fabric/gossip/api" - "github.com/hyperledger/fabric/gossip/comm" "github.com/hyperledger/fabric/gossip/common" "github.com/hyperledger/fabric/gossip/discovery" proto "github.com/hyperledger/fabric/protos/gossip" @@ -216,7 +215,7 @@ func (g *peerMockGossip) Peers() []discovery.NetworkMember { return res } -func (g *peerMockGossip) Accept(acceptor common.MessageAcceptor, passThrough bool) (<-chan *proto.GossipMessage, <-chan comm.ReceivedMessage) { +func (g *peerMockGossip) Accept(acceptor common.MessageAcceptor, passThrough bool) (<-chan *proto.GossipMessage, <-chan proto.ReceivedMessage) { ch := make(chan *proto.GossipMessage, 100) g.acceptorLock.Lock() g.acceptors = append(g.acceptors, &mockAcceptor{ diff --git a/gossip/gossip/certstore.go b/gossip/gossip/certstore.go index 7ea855506c1..ae385b92209 100644 --- a/gossip/gossip/certstore.go +++ b/gossip/gossip/certstore.go @@ -22,7 +22,6 @@ import ( "sync" "github.com/hyperledger/fabric/gossip/api" - "github.com/hyperledger/fabric/gossip/comm" "github.com/hyperledger/fabric/gossip/common" "github.com/hyperledger/fabric/gossip/gossip/pull" "github.com/hyperledger/fabric/gossip/identity" @@ -63,7 +62,7 @@ func newCertStore(puller pull.Mediator, idMapper identity.Mapper, selfIdentity a puller.Add(certStore.createIdentityMessage()) - puller.RegisterMsgHook(pull.ResponseMsgType, func(_ []string, msgs []*proto.GossipMessage, _ comm.ReceivedMessage) { + puller.RegisterMsgHook(pull.ResponseMsgType, func(_ []string, msgs []*proto.GossipMessage, _ proto.ReceivedMessage) { for _, msg := range msgs { pkiID := common.PKIidType(msg.GetPeerIdentity().PkiID) cert := api.PeerIdentityType(msg.GetPeerIdentity().Cert) @@ -78,7 +77,7 @@ func newCertStore(puller pull.Mediator, idMapper identity.Mapper, selfIdentity a return certStore } -func (cs *certStore) handleMessage(msg comm.ReceivedMessage) { +func (cs *certStore) handleMessage(msg proto.ReceivedMessage) { if update := msg.GetGossipMessage().GetDataUpdate(); update != nil { for _, m := range update.Data { if !m.IsIdentityMsg() { diff --git a/gossip/gossip/certstore_test.go b/gossip/gossip/certstore_test.go index 05a4abc8081..5fa315f7245 100644 --- a/gossip/gossip/certstore_test.go +++ b/gossip/gossip/certstore_test.go @@ -50,6 +50,12 @@ type sentMsg struct { mock.Mock } +// GetSourceMessage Returns the SignedGossipMessage the ReceivedMessage was +// constructed with +func (s *sentMsg) GetSourceMessage() *proto.SignedGossipMessage { + return nil +} + func (s *sentMsg) Respond(msg *proto.GossipMessage) { s.Called(msg) } @@ -80,7 +86,7 @@ func (m *membershipSvcMock) GetMembership() []discovery.NetworkMember { } func TestCertStoreBadSignature(t *testing.T) { - badSignature := func(nonce uint64) comm.ReceivedMessage { + badSignature := func(nonce uint64) proto.ReceivedMessage { return createUpdateMessage(nonce, createBadlySignedUpdateMessage()) } @@ -88,7 +94,7 @@ func TestCertStoreBadSignature(t *testing.T) { } func TestCertStoreMismatchedIdentity(t *testing.T) { - mismatchedIdentity := func(nonce uint64) comm.ReceivedMessage { + mismatchedIdentity := func(nonce uint64) proto.ReceivedMessage { return createUpdateMessage(nonce, createMismatchedUpdateMessage()) } @@ -96,14 +102,14 @@ func TestCertStoreMismatchedIdentity(t *testing.T) { } func TestCertStoreShouldSucceed(t *testing.T) { - totallyFineIdentity := func(nonce uint64) comm.ReceivedMessage { + totallyFineIdentity := func(nonce uint64) proto.ReceivedMessage { return createUpdateMessage(nonce, createValidUpdateMessage()) } testCertificateUpdate(t, totallyFineIdentity, true) } -func testCertificateUpdate(t *testing.T, updateFactory func(uint64) comm.ReceivedMessage, shouldSucceed bool) { +func testCertificateUpdate(t *testing.T, updateFactory func(uint64) proto.ReceivedMessage, shouldSucceed bool) { config := pull.PullConfig{ MsgType: proto.PullMsgType_IdentityMsg, PeerCountToSelect: 1, @@ -257,7 +263,7 @@ func createValidUpdateMessage() *proto.GossipMessage { return m } -func createUpdateMessage(nonce uint64, idMsg *proto.GossipMessage) comm.ReceivedMessage { +func createUpdateMessage(nonce uint64, idMsg *proto.GossipMessage) proto.ReceivedMessage { update := &proto.GossipMessage{ Tag: proto.GossipMessage_EMPTY, Content: &proto.GossipMessage_DataUpdate{ @@ -271,7 +277,7 @@ func createUpdateMessage(nonce uint64, idMsg *proto.GossipMessage) comm.Received return &sentMsg{msg: update} } -func createDigest(nonce uint64) comm.ReceivedMessage { +func createDigest(nonce uint64) proto.ReceivedMessage { digest := &proto.GossipMessage{ Tag: proto.GossipMessage_EMPTY, Content: &proto.GossipMessage_DataDig{ diff --git a/gossip/gossip/channel/channel.go b/gossip/gossip/channel/channel.go index 3571b1f77d0..0774ad09529 100644 --- a/gossip/gossip/channel/channel.go +++ b/gossip/gossip/channel/channel.go @@ -67,7 +67,7 @@ type GossipChannel interface { IsSubscribed(member discovery.NetworkMember) bool // HandleMessage processes a message sent by a remote peer - HandleMessage(comm.ReceivedMessage) + HandleMessage(proto.ReceivedMessage) // AddToMsgStore adds a given GossipMessage to the message store AddToMsgStore(msg *proto.GossipMessage) @@ -354,7 +354,7 @@ func (gc *gossipChannel) ConfigureChannel(joinMsg api.JoinChannelMessage) { } // HandleMessage processes a message sent by a remote peer -func (gc *gossipChannel) HandleMessage(msg comm.ReceivedMessage) { +func (gc *gossipChannel) HandleMessage(msg proto.ReceivedMessage) { if !gc.verifyMsg(msg) { return } @@ -500,7 +500,7 @@ func (gc *gossipChannel) createStateInfoSnapshot() *proto.GossipMessage { } } -func (gc *gossipChannel) verifyMsg(msg comm.ReceivedMessage) bool { +func (gc *gossipChannel) verifyMsg(msg proto.ReceivedMessage) bool { if msg == nil { gc.logger.Warning("Messsage is nil") return false diff --git a/gossip/gossip/channel/channel_test.go b/gossip/gossip/channel/channel_test.go index ae39fcf8bda..3a683eafad7 100644 --- a/gossip/gossip/channel/channel_test.go +++ b/gossip/gossip/channel/channel_test.go @@ -124,6 +124,12 @@ type receivedMsg struct { mock.Mock } +// GetSourceMessage Returns the SignedGossipMessage the ReceivedMessage was +// constructed with +func (m *receivedMsg) GetSourceMessage() *proto.SignedGossipMessage { + return nil +} + func (m *receivedMsg) GetGossipMessage() *proto.GossipMessage { return m.msg } diff --git a/gossip/gossip/gossip.go b/gossip/gossip/gossip.go index 23bb7aa2877..7939ffdf947 100644 --- a/gossip/gossip/gossip.go +++ b/gossip/gossip/gossip.go @@ -56,7 +56,7 @@ type Gossip interface { // If passThrough is false, the messages are processed by the gossip layer beforehand. // If passThrough is true, the gossip layer doesn't intervene and the messages // can be used to send a reply back to the sender - Accept(acceptor common.MessageAcceptor, passThrough bool) (<-chan *proto.GossipMessage, <-chan comm.ReceivedMessage) + Accept(acceptor common.MessageAcceptor, passThrough bool) (<-chan *proto.GossipMessage, <-chan proto.ReceivedMessage) // JoinChan makes the Gossip instance join a channel JoinChan(joinMsg api.JoinChannelMessage, chainID common.ChainID) diff --git a/gossip/gossip/gossip_impl.go b/gossip/gossip/gossip_impl.go index a3567631010..2e78b7aae19 100644 --- a/gossip/gossip/gossip_impl.go +++ b/gossip/gossip/gossip_impl.go @@ -236,7 +236,7 @@ func (g *gossipServiceImpl) start() { go g.handlePresumedDead() msgSelector := func(msg interface{}) bool { - gMsg, isGossipMsg := msg.(comm.ReceivedMessage) + gMsg, isGossipMsg := msg.(proto.ReceivedMessage) if !isGossipMsg { return false } @@ -254,7 +254,7 @@ func (g *gossipServiceImpl) start() { g.logger.Info("Gossip instance", g.conf.ID, "started") } -func (g *gossipServiceImpl) acceptMessages(incMsgs <-chan comm.ReceivedMessage) { +func (g *gossipServiceImpl) acceptMessages(incMsgs <-chan proto.ReceivedMessage) { defer g.logger.Debug("Exiting") g.stopSignal.Add(1) defer g.stopSignal.Done() @@ -270,7 +270,7 @@ func (g *gossipServiceImpl) acceptMessages(incMsgs <-chan comm.ReceivedMessage) } } -func (g *gossipServiceImpl) handleMessage(m comm.ReceivedMessage) { +func (g *gossipServiceImpl) handleMessage(m proto.ReceivedMessage) { if g.toDie() { return } @@ -336,7 +336,7 @@ func (g *gossipServiceImpl) handleMessage(m comm.ReceivedMessage) { } } -func (g *gossipServiceImpl) forwardDiscoveryMsg(msg comm.ReceivedMessage) { +func (g *gossipServiceImpl) forwardDiscoveryMsg(msg proto.ReceivedMessage) { defer func() { // can be closed while shutting down recover() }() @@ -345,7 +345,7 @@ func (g *gossipServiceImpl) forwardDiscoveryMsg(msg comm.ReceivedMessage) { // validateMsg checks the signature of the message if exists, // and also checks that the tag matches the message type -func (g *gossipServiceImpl) validateMsg(msg comm.ReceivedMessage) bool { +func (g *gossipServiceImpl) validateMsg(msg proto.ReceivedMessage) bool { if err := msg.GetGossipMessage().IsTagLegal(); err != nil { g.logger.Warning("Tag of", msg.GetGossipMessage(), "isn't legal:", err) return false @@ -384,7 +384,7 @@ func (g *gossipServiceImpl) validateMsg(msg comm.ReceivedMessage) bool { return true } -func (g *gossipServiceImpl) forwardToDiscoveryLayer(msg comm.ReceivedMessage) { +func (g *gossipServiceImpl) forwardToDiscoveryLayer(msg proto.ReceivedMessage) { defer func() { // can be closed while shutting down recover() }() @@ -605,7 +605,7 @@ func (g *gossipServiceImpl) UpdateChannelMetadata(md []byte, chainID common.Chai // If passThrough is false, the messages are processed by the gossip layer beforehand. // If passThrough is true, the gossip layer doesn't intervene and the messages // can be used to send a reply back to the sender -func (g *gossipServiceImpl) Accept(acceptor common.MessageAcceptor, passThrough bool) (<-chan *proto.GossipMessage, <-chan comm.ReceivedMessage) { +func (g *gossipServiceImpl) Accept(acceptor common.MessageAcceptor, passThrough bool) (<-chan *proto.GossipMessage, <-chan proto.ReceivedMessage) { if passThrough { return nil, g.comm.Accept(acceptor) } @@ -630,7 +630,7 @@ func (g *gossipServiceImpl) Accept(acceptor common.MessageAcceptor, passThrough } func selectOnlyDiscoveryMessages(m interface{}) bool { - msg, isGossipMsg := m.(comm.ReceivedMessage) + msg, isGossipMsg := m.(proto.ReceivedMessage) if !isGossipMsg { return false } diff --git a/gossip/gossip/pull/pullstore.go b/gossip/gossip/pull/pullstore.go index 94c6a3127f6..88cf6e54b8e 100644 --- a/gossip/gossip/pull/pullstore.go +++ b/gossip/gossip/pull/pullstore.go @@ -41,7 +41,7 @@ const ( type PullMsgType int // MessageHook defines a function that will run after a certain pull message is received -type MessageHook func(itemIDs []string, items []*proto.GossipMessage, msg comm.ReceivedMessage) +type MessageHook func(itemIDs []string, items []*proto.GossipMessage, msg proto.ReceivedMessage) // Sender sends messages to remote peers type Sender interface { @@ -85,7 +85,7 @@ type Mediator interface { Remove(*proto.GossipMessage) // HandleMessage handles a message from some remote peer - HandleMessage(msg comm.ReceivedMessage) + HandleMessage(msg proto.ReceivedMessage) } // pullMediatorImpl is an implementation of Mediator @@ -118,7 +118,7 @@ func NewPullMediator(config PullConfig, sndr Sender, memSvc MembershipService, i return p } -func (p *pullMediatorImpl) HandleMessage(m comm.ReceivedMessage) { +func (p *pullMediatorImpl) HandleMessage(m proto.ReceivedMessage) { if m.GetGossipMessage() == nil || !m.GetGossipMessage().IsPullMsg() { return } @@ -246,7 +246,7 @@ func (p *pullMediatorImpl) SendDigest(digest []string, nonce uint64, context int }, } p.logger.Debug("Sending digest", digMsg.GetDataDig().Digests) - context.(comm.ReceivedMessage).Respond(digMsg) + context.(proto.ReceivedMessage).Respond(digMsg) } // SendReq sends an array of items to a certain remote PullEngine identified @@ -292,7 +292,7 @@ func (p *pullMediatorImpl) SendRes(items []string, context interface{}, nonce ui }, } p.logger.Debug("Sending", returnedUpdate, "to") - context.(comm.ReceivedMessage).Respond(returnedUpdate) + context.(proto.ReceivedMessage).Respond(returnedUpdate) } func (p *pullMediatorImpl) peersWithEndpoints(endpoints ...string) []*comm.RemotePeer { diff --git a/gossip/gossip/pull/pullstore_test.go b/gossip/gossip/pull/pullstore_test.go index 375008530d4..ad4f982ab00 100644 --- a/gossip/gossip/pull/pullstore_test.go +++ b/gossip/gossip/pull/pullstore_test.go @@ -46,6 +46,12 @@ type pullMsg struct { msg *proto.GossipMessage } +// GetSourceMessage Returns the SignedGossipMessage the ReceivedMessage was +// constructed with +func (pm *pullMsg) GetSourceMessage() *proto.SignedGossipMessage { + return nil +} + func (pm *pullMsg) Respond(msg *proto.GossipMessage) { pm.respondChan <- &pullMsg{ msg: msg, @@ -93,7 +99,7 @@ func (p *pullInstance) stop() { p.stopChan <- struct{}{} } -func (p *pullInstance) wrapPullMsg(msg *proto.GossipMessage) comm.ReceivedMessage { +func (p *pullInstance) wrapPullMsg(msg *proto.GossipMessage) proto.ReceivedMessage { return &pullMsg{ msg: msg, respondChan: p.msgChan, @@ -164,7 +170,7 @@ func TestRegisterMsgHook(t *testing.T) { for _, msgType := range []PullMsgType{HelloMsgType, DigestMsgType, RequestMsgType, ResponseMsgType} { mType := msgType - inst1.mediator.RegisterMsgHook(mType, func(_ []string, items []*proto.GossipMessage, _ comm.ReceivedMessage) { + inst1.mediator.RegisterMsgHook(mType, func(_ []string, items []*proto.GossipMessage, _ proto.ReceivedMessage) { receivedMsgTypes.Add(mType) }) } @@ -226,7 +232,7 @@ func TestHandleMessage(t *testing.T) { inst1ReceivedDigest := int32(0) inst1ReceivedResponse := int32(0) - inst1.mediator.RegisterMsgHook(DigestMsgType, func(itemIds []string, _ []*proto.GossipMessage, _ comm.ReceivedMessage) { + inst1.mediator.RegisterMsgHook(DigestMsgType, func(itemIds []string, _ []*proto.GossipMessage, _ proto.ReceivedMessage) { if atomic.LoadInt32(&inst1ReceivedDigest) == int32(1) { return } @@ -234,7 +240,7 @@ func TestHandleMessage(t *testing.T) { assert.True(t, len(itemIds) == 3) }) - inst1.mediator.RegisterMsgHook(ResponseMsgType, func(_ []string, items []*proto.GossipMessage, _ comm.ReceivedMessage) { + inst1.mediator.RegisterMsgHook(ResponseMsgType, func(_ []string, items []*proto.GossipMessage, _ proto.ReceivedMessage) { if atomic.LoadInt32(&inst1ReceivedResponse) == int32(1) { return } diff --git a/gossip/state/state.go b/gossip/state/state.go index e7e4ed6d4b4..e6789154f3c 100644 --- a/gossip/state/state.go +++ b/gossip/state/state.go @@ -48,7 +48,7 @@ type GossipStateProvider interface { } var remoteStateMsgFilter = func(message interface{}) bool { - return message.(comm.ReceivedMessage).GetGossipMessage().IsRemoteStateMessage() + return message.(proto.ReceivedMessage).GetGossipMessage().IsRemoteStateMessage() } const ( @@ -69,7 +69,7 @@ type GossipStateProviderImpl struct { // Channel to read gossip messages from gossipChan <-chan *proto.GossipMessage - commChan <-chan comm.ReceivedMessage + commChan <-chan proto.ReceivedMessage // Flag which signals for termination stopFlag int32 @@ -177,7 +177,7 @@ func (s *GossipStateProviderImpl) listen() { s.done.Done() } -func (s *GossipStateProviderImpl) directMessage(msg comm.ReceivedMessage) { +func (s *GossipStateProviderImpl) directMessage(msg proto.ReceivedMessage) { s.logger.Debug("[ENTER] -> directMessage") defer s.logger.Debug("[EXIT] -> directMessage") @@ -201,7 +201,7 @@ func (s *GossipStateProviderImpl) directMessage(msg comm.ReceivedMessage) { } } -func (s *GossipStateProviderImpl) handleStateRequest(msg comm.ReceivedMessage) { +func (s *GossipStateProviderImpl) handleStateRequest(msg proto.ReceivedMessage) { request := msg.GetGossipMessage().GetStateRequest() response := &proto.RemoteStateResponse{Payloads: make([]*proto.Payload, 0)} for _, seqNum := range request.SeqNums { @@ -233,7 +233,7 @@ func (s *GossipStateProviderImpl) handleStateRequest(msg comm.ReceivedMessage) { }) } -func (s *GossipStateProviderImpl) handleStateResponse(msg comm.ReceivedMessage) { +func (s *GossipStateProviderImpl) handleStateResponse(msg proto.ReceivedMessage) { response := msg.GetGossipMessage().GetStateResponse() for _, payload := range response.GetPayloads() { s.logger.Debugf("Received payload with sequence number %d.", payload.SeqNum) diff --git a/protos/gossip/extensions.go b/protos/gossip/extensions.go index de10523ddb9..b0611f5df80 100644 --- a/protos/gossip/extensions.go +++ b/protos/gossip/extensions.go @@ -303,6 +303,29 @@ func (m *GossipMessage) IsTagLegal() error { type Verifier func(peerIdentity []byte, signature, message []byte) error type Signer func(msg []byte) ([]byte, error) +// ReceivedMessage is a GossipMessage wrapper that +// enables the user to send a message to the origin from which +// the ReceivedMessage was sent from. +// It also allows to know the identity of the sender, +// to obtain the raw bytes the GossipMessage was un-marshaled from, +// and the signature over these raw bytes. +type ReceivedMessage interface { + + // Respond sends a GossipMessage to the origin from which this ReceivedMessage was sent from + Respond(msg *GossipMessage) + + // GetGossipMessage returns the underlying GossipMessage + GetGossipMessage() *GossipMessage + + // GetSourceMessage Returns the SignedGossipMessage the ReceivedMessage was + // constructed with + GetSourceMessage() *SignedGossipMessage + + // GetPKIID returns the PKI-ID of the remote peer + // that sent the message + GetPKIID() common.PKIidType +} + // Sign signs a GossipMessage with given Signer. // Returns a signed message on success // or an error on failure diff --git a/protos/gossip/message.pb.go b/protos/gossip/message.pb.go index fa514911a41..70ebd3e5c00 100644 --- a/protos/gossip/message.pb.go +++ b/protos/gossip/message.pb.go @@ -9,6 +9,7 @@ It is generated from these files: gossip/message.proto It has these top-level messages: + SignedGossipMessage GossipMessage StateInfo StateInfoSnapshot @@ -109,7 +110,19 @@ var GossipMessage_Tag_value = map[string]int32{ func (x GossipMessage_Tag) String() string { return proto.EnumName(GossipMessage_Tag_name, int32(x)) } -func (GossipMessage_Tag) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} } +func (GossipMessage_Tag) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1, 0} } + +// GossipMessage contains a marshalled +// GossipMessage and a signature over it. +type SignedGossipMessage struct { + Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (m *SignedGossipMessage) Reset() { *m = SignedGossipMessage{} } +func (m *SignedGossipMessage) String() string { return proto.CompactTextString(m) } +func (*SignedGossipMessage) ProtoMessage() {} +func (*SignedGossipMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } // GossipMessage defines the message sent in a gossip network type GossipMessage struct { @@ -148,7 +161,7 @@ type GossipMessage struct { func (m *GossipMessage) Reset() { *m = GossipMessage{} } func (m *GossipMessage) String() string { return proto.CompactTextString(m) } func (*GossipMessage) ProtoMessage() {} -func (*GossipMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*GossipMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } type isGossipMessage_Content interface { isGossipMessage_Content() @@ -720,7 +733,7 @@ type StateInfo struct { func (m *StateInfo) Reset() { *m = StateInfo{} } func (m *StateInfo) String() string { return proto.CompactTextString(m) } func (*StateInfo) ProtoMessage() {} -func (*StateInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*StateInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (m *StateInfo) GetTimestamp() *PeerTime { if m != nil { @@ -737,7 +750,7 @@ type StateInfoSnapshot struct { func (m *StateInfoSnapshot) Reset() { *m = StateInfoSnapshot{} } func (m *StateInfoSnapshot) String() string { return proto.CompactTextString(m) } func (*StateInfoSnapshot) ProtoMessage() {} -func (*StateInfoSnapshot) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (*StateInfoSnapshot) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (m *StateInfoSnapshot) GetElements() []*GossipMessage { if m != nil { @@ -754,7 +767,7 @@ type StateInfoPullRequest struct { func (m *StateInfoPullRequest) Reset() { *m = StateInfoPullRequest{} } func (m *StateInfoPullRequest) String() string { return proto.CompactTextString(m) } func (*StateInfoPullRequest) ProtoMessage() {} -func (*StateInfoPullRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (*StateInfoPullRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } // ConnEstablish is the message used for the gossip handshake // Whenever a peer connects to another peer, it handshakes @@ -768,7 +781,7 @@ type ConnEstablish struct { func (m *ConnEstablish) Reset() { *m = ConnEstablish{} } func (m *ConnEstablish) String() string { return proto.CompactTextString(m) } func (*ConnEstablish) ProtoMessage() {} -func (*ConnEstablish) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (*ConnEstablish) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } // PeerIdentity defines the identity of the peer // Used to make other peers learn of the identity @@ -782,7 +795,7 @@ type PeerIdentity struct { func (m *PeerIdentity) Reset() { *m = PeerIdentity{} } func (m *PeerIdentity) String() string { return proto.CompactTextString(m) } func (*PeerIdentity) ProtoMessage() {} -func (*PeerIdentity) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } +func (*PeerIdentity) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } // DataRequest is a message used for a peer to request // certain data blocks from a remote peer @@ -795,7 +808,7 @@ type DataRequest struct { func (m *DataRequest) Reset() { *m = DataRequest{} } func (m *DataRequest) String() string { return proto.CompactTextString(m) } func (*DataRequest) ProtoMessage() {} -func (*DataRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } +func (*DataRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } // GossipHello is the message that is used for the peer to initiate // a pull round with another peer @@ -808,7 +821,7 @@ type GossipHello struct { func (m *GossipHello) Reset() { *m = GossipHello{} } func (m *GossipHello) String() string { return proto.CompactTextString(m) } func (*GossipHello) ProtoMessage() {} -func (*GossipHello) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } +func (*GossipHello) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } // DataUpdate is the the final message in the pull phase // sent from the receiver to the initiator @@ -821,7 +834,7 @@ type DataUpdate struct { func (m *DataUpdate) Reset() { *m = DataUpdate{} } func (m *DataUpdate) String() string { return proto.CompactTextString(m) } func (*DataUpdate) ProtoMessage() {} -func (*DataUpdate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (*DataUpdate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } func (m *DataUpdate) GetData() []*GossipMessage { if m != nil { @@ -841,7 +854,7 @@ type DataDigest struct { func (m *DataDigest) Reset() { *m = DataDigest{} } func (m *DataDigest) String() string { return proto.CompactTextString(m) } func (*DataDigest) ProtoMessage() {} -func (*DataDigest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (*DataDigest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } // DataMessage is the message that contains a block type DataMessage struct { @@ -851,7 +864,7 @@ type DataMessage struct { func (m *DataMessage) Reset() { *m = DataMessage{} } func (m *DataMessage) String() string { return proto.CompactTextString(m) } func (*DataMessage) ProtoMessage() {} -func (*DataMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (*DataMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } func (m *DataMessage) GetPayload() *Payload { if m != nil { @@ -870,7 +883,7 @@ type Payload struct { func (m *Payload) Reset() { *m = Payload{} } func (m *Payload) String() string { return proto.CompactTextString(m) } func (*Payload) ProtoMessage() {} -func (*Payload) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (*Payload) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } // AliveMessage is sent to inform remote peers // of a peer's existence and activity @@ -883,7 +896,7 @@ type AliveMessage struct { func (m *AliveMessage) Reset() { *m = AliveMessage{} } func (m *AliveMessage) String() string { return proto.CompactTextString(m) } func (*AliveMessage) ProtoMessage() {} -func (*AliveMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } +func (*AliveMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } func (m *AliveMessage) GetMembership() *Member { if m != nil { @@ -910,7 +923,7 @@ type LeadershipMessage struct { func (m *LeadershipMessage) Reset() { *m = LeadershipMessage{} } func (m *LeadershipMessage) String() string { return proto.CompactTextString(m) } func (*LeadershipMessage) ProtoMessage() {} -func (*LeadershipMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (*LeadershipMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } func (m *LeadershipMessage) GetTimestamp() *PeerTime { if m != nil { @@ -928,7 +941,7 @@ type PeerTime struct { func (m *PeerTime) Reset() { *m = PeerTime{} } func (m *PeerTime) String() string { return proto.CompactTextString(m) } func (*PeerTime) ProtoMessage() {} -func (*PeerTime) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (*PeerTime) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } // MembershipRequest is used to ask membership information // from a remote peer @@ -940,7 +953,7 @@ type MembershipRequest struct { func (m *MembershipRequest) Reset() { *m = MembershipRequest{} } func (m *MembershipRequest) String() string { return proto.CompactTextString(m) } func (*MembershipRequest) ProtoMessage() {} -func (*MembershipRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } +func (*MembershipRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } func (m *MembershipRequest) GetSelfInformation() *GossipMessage { if m != nil { @@ -958,7 +971,7 @@ type MembershipResponse struct { func (m *MembershipResponse) Reset() { *m = MembershipResponse{} } func (m *MembershipResponse) String() string { return proto.CompactTextString(m) } func (*MembershipResponse) ProtoMessage() {} -func (*MembershipResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (*MembershipResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } func (m *MembershipResponse) GetAlive() []*GossipMessage { if m != nil { @@ -988,7 +1001,7 @@ type Member struct { func (m *Member) Reset() { *m = Member{} } func (m *Member) String() string { return proto.CompactTextString(m) } func (*Member) ProtoMessage() {} -func (*Member) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } +func (*Member) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } func (m *Member) GetInternalEndpoint() *SignedEndpoint { if m != nil { @@ -1010,7 +1023,7 @@ type SignedEndpoint struct { func (m *SignedEndpoint) Reset() { *m = SignedEndpoint{} } func (m *SignedEndpoint) String() string { return proto.CompactTextString(m) } func (*SignedEndpoint) ProtoMessage() {} -func (*SignedEndpoint) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (*SignedEndpoint) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } // Empty is used for pinging and in tests type Empty struct { @@ -1019,7 +1032,7 @@ type Empty struct { func (m *Empty) Reset() { *m = Empty{} } func (m *Empty) String() string { return proto.CompactTextString(m) } func (*Empty) ProtoMessage() {} -func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } +func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } // RemoteStateRequest is used to ask a set of blocks // from a remote peer @@ -1030,7 +1043,7 @@ type RemoteStateRequest struct { func (m *RemoteStateRequest) Reset() { *m = RemoteStateRequest{} } func (m *RemoteStateRequest) String() string { return proto.CompactTextString(m) } func (*RemoteStateRequest) ProtoMessage() {} -func (*RemoteStateRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } +func (*RemoteStateRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } // RemoteStateResponse is used to send a set of blocks // to a remote peer @@ -1041,7 +1054,7 @@ type RemoteStateResponse struct { func (m *RemoteStateResponse) Reset() { *m = RemoteStateResponse{} } func (m *RemoteStateResponse) String() string { return proto.CompactTextString(m) } func (*RemoteStateResponse) ProtoMessage() {} -func (*RemoteStateResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } +func (*RemoteStateResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } func (m *RemoteStateResponse) GetPayloads() []*Payload { if m != nil { @@ -1051,6 +1064,7 @@ func (m *RemoteStateResponse) GetPayloads() []*Payload { } func init() { + proto.RegisterType((*SignedGossipMessage)(nil), "gossip.SignedGossipMessage") proto.RegisterType((*GossipMessage)(nil), "gossip.GossipMessage") proto.RegisterType((*StateInfo)(nil), "gossip.StateInfo") proto.RegisterType((*StateInfoSnapshot)(nil), "gossip.StateInfoSnapshot") @@ -1222,83 +1236,84 @@ var _Gossip_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("gossip/message.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1240 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x57, 0x5f, 0x6f, 0xdb, 0x36, - 0x10, 0xb7, 0xfc, 0x5f, 0x67, 0x3b, 0x51, 0xd8, 0xb4, 0xd0, 0xb2, 0x0e, 0x08, 0x84, 0x6d, 0x48, - 0x17, 0xd4, 0x59, 0xd3, 0x3e, 0x0c, 0x7b, 0xe9, 0x92, 0x3a, 0xad, 0x53, 0xd4, 0x6e, 0xc0, 0xa4, - 0x0f, 0xdd, 0x4b, 0xc0, 0x58, 0x8c, 0xac, 0x45, 0xa2, 0x54, 0x91, 0xd9, 0x10, 0x60, 0xc0, 0xde, - 0xf7, 0x11, 0xf6, 0x01, 0xf6, 0x39, 0x07, 0x92, 0xa2, 0x2c, 0xd5, 0x4e, 0x86, 0x0c, 0xd8, 0x9b, - 0xee, 0xf8, 0xbb, 0x3f, 0xbc, 0x3b, 0xde, 0x9d, 0x60, 0x33, 0x48, 0x38, 0x0f, 0xd3, 0xbd, 0x98, - 0x72, 0x4e, 0x02, 0x3a, 0x4c, 0xb3, 0x44, 0x24, 0xa8, 0xad, 0xb9, 0xde, 0xdf, 0x36, 0x0c, 0xde, - 0xa8, 0xcf, 0x89, 0x3e, 0x47, 0x9b, 0xd0, 0x62, 0x09, 0x9b, 0x51, 0xd7, 0xda, 0xb6, 0x76, 0x9a, - 0x58, 0x13, 0xc8, 0x85, 0xce, 0x6c, 0x4e, 0x18, 0xa3, 0x91, 0x5b, 0xdf, 0xb6, 0x76, 0xfa, 0xd8, - 0x90, 0x68, 0x17, 0x1a, 0x82, 0x04, 0x6e, 0x63, 0xdb, 0xda, 0x59, 0xdb, 0xff, 0x62, 0xa8, 0xf5, - 0x0e, 0x2b, 0x3a, 0x87, 0x67, 0x24, 0xc0, 0x12, 0x85, 0x1e, 0x83, 0xcd, 0xc3, 0x80, 0x11, 0x71, - 0x9d, 0x51, 0xb7, 0xa9, 0x14, 0x2d, 0x18, 0x68, 0x1f, 0xba, 0x24, 0x0a, 0x7f, 0xa5, 0x13, 0x1e, - 0xb8, 0xad, 0x6d, 0x6b, 0xa7, 0xb7, 0xbf, 0x69, 0xf4, 0x1d, 0x28, 0xbe, 0x56, 0x37, 0xae, 0xe1, - 0x02, 0x87, 0x9e, 0x43, 0x3b, 0xa6, 0x31, 0xa6, 0x9f, 0xdc, 0xb6, 0x92, 0x28, 0x3c, 0x98, 0xd0, - 0xf8, 0x82, 0x66, 0x7c, 0x1e, 0xa6, 0x98, 0x7e, 0xba, 0xa6, 0x5c, 0x8c, 0x6b, 0x38, 0x87, 0xa2, - 0x17, 0xb9, 0x10, 0x77, 0x3b, 0x4a, 0x68, 0x6b, 0x95, 0x10, 0x4f, 0x13, 0xc6, 0x69, 0x21, 0xc5, - 0xd1, 0x1e, 0x74, 0x7c, 0x22, 0x88, 0xf4, 0xae, 0xab, 0xc4, 0x1e, 0x18, 0xb1, 0x91, 0x64, 0x17, - 0xce, 0x19, 0x14, 0xda, 0x85, 0xd6, 0x9c, 0x46, 0x51, 0xe2, 0xda, 0x55, 0xb8, 0x0e, 0xce, 0x58, - 0x1e, 0x8d, 0x6b, 0x58, 0x63, 0xd0, 0x50, 0x6b, 0x1f, 0x85, 0x81, 0x0b, 0x0a, 0x8e, 0xca, 0xda, - 0x47, 0x61, 0xa0, 0xaf, 0x60, 0x40, 0xc6, 0x1b, 0x79, 0xf3, 0xde, 0xb2, 0x37, 0x8b, 0x3b, 0x1b, - 0x14, 0x7a, 0x01, 0x20, 0x3f, 0x3f, 0xa4, 0x3e, 0x11, 0xd4, 0xed, 0x2f, 0xdb, 0xd0, 0x27, 0xe3, - 0x1a, 0x2e, 0xe1, 0xd0, 0x37, 0xd0, 0xa2, 0x71, 0x2a, 0x6e, 0xdc, 0x81, 0x12, 0x18, 0x18, 0x81, - 0x23, 0xc9, 0x94, 0xde, 0xab, 0x53, 0xb4, 0x0b, 0xcd, 0x59, 0xc2, 0x98, 0xbb, 0xa6, 0x50, 0x0f, - 0x0d, 0xea, 0x55, 0xc2, 0xd8, 0x11, 0x17, 0xe4, 0x22, 0x0a, 0xf9, 0x7c, 0x5c, 0xc3, 0x0a, 0x84, - 0x9e, 0x81, 0xcd, 0x05, 0x11, 0xf4, 0x98, 0x5d, 0x26, 0xee, 0xba, 0x92, 0xd8, 0x30, 0x12, 0xa7, - 0xe6, 0x60, 0x5c, 0xc3, 0x0b, 0x14, 0x3a, 0x80, 0x81, 0x22, 0x4e, 0x19, 0x49, 0xf9, 0x3c, 0x11, - 0xae, 0x53, 0xcd, 0x76, 0x21, 0x66, 0x00, 0xe3, 0x1a, 0xae, 0x4a, 0xa0, 0xb7, 0xe0, 0x14, 0xfa, - 0x4e, 0xae, 0xa3, 0x48, 0x46, 0x6e, 0x43, 0x69, 0x79, 0xbc, 0xa4, 0x25, 0x3f, 0xcf, 0x43, 0xb8, - 0x24, 0x87, 0x7e, 0x82, 0xbe, 0xe2, 0xe5, 0x18, 0x17, 0x55, 0xcb, 0x08, 0xd3, 0x38, 0x11, 0xf4, - 0xb4, 0x84, 0x18, 0xd7, 0x70, 0x45, 0x02, 0xbd, 0xca, 0x2f, 0x64, 0xea, 0xcc, 0x7d, 0xa0, 0x54, - 0x7c, 0xb9, 0x52, 0x45, 0x51, 0x8a, 0x55, 0x19, 0x19, 0x95, 0x88, 0x12, 0x5f, 0x57, 0xac, 0xac, - 0xcb, 0xcd, 0x6a, 0x54, 0xde, 0x2d, 0x0e, 0x8b, 0xea, 0xac, 0x4a, 0xa0, 0x1f, 0xa1, 0x9f, 0x52, - 0x9a, 0x1d, 0xfb, 0x94, 0x89, 0x50, 0xdc, 0xb8, 0x0f, 0xab, 0xef, 0xee, 0xa4, 0x74, 0x26, 0xef, - 0x50, 0xc6, 0x7a, 0xe7, 0xd0, 0x38, 0x23, 0x01, 0x1a, 0x80, 0xfd, 0x61, 0x3a, 0x3a, 0x7a, 0x7d, - 0x3c, 0x3d, 0x1a, 0x39, 0x35, 0x64, 0x43, 0xeb, 0x68, 0x72, 0x72, 0xf6, 0xd1, 0xb1, 0x50, 0x1f, - 0xba, 0xef, 0xf1, 0x9b, 0xf3, 0xf7, 0xd3, 0x77, 0x1f, 0x9d, 0xba, 0xc4, 0xbd, 0x1a, 0x1f, 0x4c, - 0x35, 0xd9, 0x40, 0x0e, 0xf4, 0x15, 0x79, 0x30, 0x1d, 0x9d, 0xbf, 0xc7, 0x6f, 0x9c, 0x26, 0x5a, - 0x87, 0x9e, 0x06, 0x60, 0xc5, 0x68, 0x1d, 0xda, 0xd0, 0x99, 0x25, 0x4c, 0x50, 0x26, 0xbc, 0x18, - 0xec, 0x22, 0x3b, 0x68, 0x0b, 0xba, 0x31, 0x15, 0x44, 0x96, 0xa9, 0x6a, 0x53, 0x7d, 0x5c, 0xd0, - 0x68, 0x08, 0xb6, 0x08, 0x63, 0xca, 0x05, 0x89, 0x53, 0xd5, 0xab, 0x7a, 0xfb, 0x4e, 0xf9, 0x36, - 0x67, 0x61, 0x4c, 0xf1, 0x02, 0x22, 0xfb, 0x5d, 0x7a, 0x15, 0x1e, 0x8f, 0x54, 0x07, 0xeb, 0x63, - 0x4d, 0x78, 0xaf, 0x61, 0x63, 0xa9, 0xa4, 0xd0, 0x33, 0xe8, 0xd2, 0x88, 0xc6, 0x94, 0x09, 0xee, - 0x5a, 0xdb, 0x8d, 0x72, 0xa1, 0x57, 0xfa, 0x1d, 0x2e, 0x60, 0xde, 0x23, 0xd8, 0x5c, 0x55, 0x54, - 0xde, 0x04, 0x06, 0x95, 0xb7, 0xb1, 0x70, 0xc3, 0x2a, 0xb9, 0x81, 0x10, 0x34, 0x67, 0x34, 0x13, - 0x79, 0xcf, 0x55, 0xdf, 0x92, 0x37, 0x27, 0x7c, 0x9e, 0xfb, 0xab, 0xbe, 0xbd, 0x33, 0xe8, 0x97, - 0x33, 0x75, 0x0f, 0x6d, 0xe5, 0x50, 0x36, 0xaa, 0xa1, 0xf4, 0x22, 0xe8, 0x95, 0x7a, 0xc9, 0xed, - 0x93, 0xc1, 0x57, 0xcd, 0x89, 0xbb, 0xf5, 0xed, 0xc6, 0x8e, 0x8d, 0x0d, 0x89, 0x9e, 0x42, 0x27, - 0xe6, 0xc1, 0xd9, 0x4d, 0x4a, 0xf3, 0xe9, 0x50, 0x74, 0x28, 0x19, 0x89, 0x89, 0x3e, 0xc2, 0x06, - 0xe3, 0x31, 0xe8, 0x95, 0x1a, 0xe3, 0x2d, 0xd6, 0xca, 0xee, 0xd6, 0x3f, 0xcb, 0xfc, 0x3d, 0xed, - 0xfd, 0x0e, 0xb0, 0xe8, 0x7a, 0xb7, 0x98, 0x7b, 0x02, 0xcd, 0xdc, 0xd4, 0x1d, 0xd9, 0x6e, 0xfe, - 0x17, 0xeb, 0x57, 0xda, 0xba, 0xee, 0xeb, 0xff, 0x77, 0x68, 0x7f, 0xd0, 0x89, 0x34, 0x23, 0xfe, - 0x09, 0x74, 0x52, 0x72, 0x13, 0x25, 0xc4, 0x57, 0xf6, 0x7a, 0xfb, 0xeb, 0x85, 0xb4, 0x66, 0x63, - 0x73, 0xee, 0x1d, 0x43, 0x27, 0xe7, 0xa1, 0x47, 0xd0, 0xe6, 0xf4, 0xd3, 0xf4, 0x3a, 0xce, 0x9d, - 0xcc, 0xa9, 0xa2, 0x1e, 0x65, 0x3a, 0x6c, 0x5d, 0x8f, 0x92, 0x57, 0xaa, 0x28, 0xf5, 0xed, 0xfd, - 0x69, 0x41, 0xbf, 0x3c, 0xc6, 0xd1, 0x10, 0x20, 0x2e, 0xe6, 0x6d, 0xee, 0xc9, 0x5a, 0x75, 0x12, - 0xe3, 0x12, 0xe2, 0xde, 0x2f, 0x7b, 0x0b, 0xba, 0xa1, 0x69, 0x6b, 0x7a, 0xd7, 0x28, 0x68, 0xef, - 0x0f, 0xd8, 0x58, 0x6a, 0x8e, 0xb7, 0xbc, 0x9a, 0xfb, 0x9a, 0xfd, 0x1a, 0x06, 0x21, 0x1f, 0xd1, - 0x59, 0x44, 0x32, 0x22, 0xc2, 0x84, 0xa9, 0x20, 0x74, 0x71, 0x95, 0xe9, 0x1d, 0x40, 0xd7, 0x08, - 0xa3, 0xaf, 0x00, 0x42, 0x36, 0x3b, 0x67, 0xd7, 0xf2, 0xaa, 0x79, 0x74, 0xed, 0x90, 0xcd, 0xa6, - 0x8a, 0x51, 0x0a, 0x7c, 0xbd, 0x1c, 0x78, 0xef, 0x17, 0xd8, 0x58, 0x5a, 0x72, 0xd0, 0x4b, 0x58, - 0xe7, 0x34, 0xba, 0x94, 0xfd, 0x26, 0x8b, 0xb5, 0x7d, 0xab, 0x3a, 0x93, 0xab, 0xc5, 0xfb, 0x39, - 0x5a, 0x06, 0xe1, 0x8a, 0x25, 0xbf, 0x31, 0x55, 0x72, 0x7d, 0xac, 0x09, 0x2f, 0x02, 0xb4, 0xbc, - 0x1b, 0xc9, 0x05, 0x47, 0x2d, 0x62, 0x77, 0x77, 0x43, 0x8d, 0x51, 0x6f, 0x89, 0x12, 0xff, 0xdf, - 0xde, 0x12, 0x25, 0xbe, 0xf7, 0x97, 0x05, 0x6d, 0x6d, 0x4e, 0x26, 0x91, 0x32, 0x3f, 0x4d, 0x42, - 0x26, 0xd4, 0x45, 0x6c, 0x5c, 0xd0, 0x77, 0x36, 0x83, 0x95, 0x6d, 0x1d, 0x1d, 0x82, 0x13, 0x32, - 0x41, 0x33, 0x46, 0xa2, 0x23, 0xa3, 0xb5, 0xa9, 0xc2, 0xf3, 0xa8, 0xd8, 0x01, 0xc2, 0x80, 0x51, - 0xdf, 0x9c, 0xe2, 0x25, 0xbc, 0xf7, 0x16, 0xd6, 0xaa, 0x98, 0x3b, 0x7d, 0xac, 0x6c, 0xbc, 0xf5, - 0xcf, 0x36, 0x5e, 0xaf, 0x03, 0x2d, 0xb5, 0x48, 0x79, 0x43, 0x40, 0xcb, 0x4b, 0x83, 0x6c, 0x00, - 0x3a, 0xd7, 0x7a, 0xde, 0x34, 0xb1, 0x21, 0xbd, 0x43, 0x78, 0xb0, 0x62, 0x43, 0x40, 0xbb, 0xd0, - 0xcd, 0x5f, 0xae, 0x99, 0x50, 0x4b, 0x4f, 0xbb, 0x00, 0x7c, 0xf7, 0x12, 0x7a, 0xa5, 0x6e, 0xa1, - 0xc6, 0x38, 0xf3, 0xe9, 0x65, 0xc8, 0xa8, 0xef, 0xd4, 0xe4, 0x78, 0x3e, 0x8c, 0x92, 0xd9, 0x55, - 0x9e, 0x19, 0xc7, 0x92, 0xe3, 0xd9, 0x0c, 0x98, 0x09, 0x0f, 0x9c, 0xfa, 0xbe, 0x80, 0xb6, 0xce, - 0x1e, 0x3a, 0x84, 0xbe, 0xfe, 0x3a, 0x15, 0x19, 0x25, 0x31, 0x5a, 0x9d, 0xdd, 0xad, 0xd5, 0x6c, - 0xaf, 0xb6, 0x63, 0x7d, 0x6f, 0xa1, 0x6f, 0xa1, 0x79, 0x12, 0xb2, 0x00, 0x55, 0x57, 0xcc, 0xad, - 0x2a, 0xe9, 0xd5, 0x0e, 0x9f, 0xfe, 0xbc, 0x1b, 0x84, 0x62, 0x7e, 0x7d, 0x31, 0x9c, 0x25, 0xf1, - 0xde, 0xfc, 0x26, 0xa5, 0x59, 0x44, 0xfd, 0x80, 0x66, 0x7b, 0x97, 0xe4, 0x22, 0x0b, 0x67, 0x7b, - 0xea, 0x0f, 0x87, 0xef, 0x69, 0xb1, 0x8b, 0xb6, 0x22, 0x9f, 0xff, 0x13, 0x00, 0x00, 0xff, 0xff, - 0xb6, 0xae, 0xe4, 0xb6, 0x08, 0x0d, 0x00, 0x00, + // 1250 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x57, 0x5f, 0x4f, 0xdc, 0x46, + 0x10, 0x3f, 0x73, 0x7f, 0x3d, 0x77, 0x07, 0x66, 0x21, 0x91, 0x4b, 0x53, 0x09, 0x59, 0x6d, 0x45, + 0x8a, 0x72, 0x34, 0x24, 0x0f, 0x55, 0x5f, 0x52, 0xc8, 0x91, 0x1c, 0x51, 0xee, 0x82, 0x16, 0xf2, + 0x90, 0xbe, 0xa0, 0xe5, 0xbc, 0xf8, 0x5c, 0xec, 0xb5, 0xe3, 0x5d, 0x5a, 0x21, 0x55, 0xea, 0x7b, + 0x3f, 0x42, 0x3f, 0x40, 0x3f, 0x67, 0xb5, 0xbb, 0x5e, 0x9f, 0xcd, 0x1d, 0x54, 0x54, 0xea, 0x9b, + 0x67, 0xf6, 0x37, 0x7f, 0x76, 0x66, 0x76, 0x66, 0x0c, 0x9b, 0x41, 0xc2, 0x79, 0x98, 0xee, 0xc5, + 0x94, 0x73, 0x12, 0xd0, 0x41, 0x9a, 0x25, 0x22, 0x41, 0x2d, 0xcd, 0xf5, 0xc6, 0xb0, 0x71, 0x1a, + 0x06, 0x8c, 0xfa, 0x6f, 0x15, 0x3d, 0xd6, 0x20, 0xe4, 0x42, 0x3b, 0x25, 0x37, 0x51, 0x42, 0x7c, + 0xd7, 0xda, 0xb6, 0x76, 0x7a, 0xd8, 0x90, 0xe8, 0x09, 0xd8, 0x3c, 0x0c, 0x18, 0x11, 0xd7, 0x19, + 0x75, 0x57, 0xd4, 0xd9, 0x9c, 0xe1, 0xfd, 0x6d, 0x43, 0xbf, 0xaa, 0x69, 0x13, 0x9a, 0x2c, 0x61, + 0x53, 0xaa, 0xf4, 0x34, 0xb0, 0x26, 0xa4, 0xfe, 0xe9, 0x8c, 0x30, 0x46, 0xa3, 0x5c, 0x87, 0x21, + 0xd1, 0x2e, 0xd4, 0x05, 0x09, 0xdc, 0xfa, 0xb6, 0xb5, 0xb3, 0xba, 0xff, 0xc5, 0x40, 0xbb, 0x39, + 0xa8, 0xe8, 0x1c, 0x9c, 0x91, 0x00, 0x4b, 0x54, 0xd5, 0x99, 0xc6, 0x2d, 0x67, 0xd0, 0x3e, 0x74, + 0x48, 0x14, 0xfe, 0x4a, 0xc7, 0x3c, 0x70, 0x9b, 0xdb, 0xd6, 0x4e, 0x77, 0x7f, 0xd3, 0xe8, 0x3b, + 0x50, 0x7c, 0xad, 0x6e, 0x54, 0xc3, 0x05, 0x0e, 0xbd, 0x80, 0x56, 0x4c, 0x63, 0x4c, 0x3f, 0xbb, + 0x2d, 0x25, 0x51, 0x78, 0x30, 0xa6, 0xf1, 0x05, 0xcd, 0xf8, 0x2c, 0x4c, 0x31, 0xfd, 0x7c, 0x4d, + 0xb9, 0x18, 0xd5, 0x70, 0x0e, 0x45, 0x2f, 0x73, 0x21, 0xee, 0xb6, 0x95, 0xd0, 0xd6, 0x32, 0x21, + 0x9e, 0x26, 0x8c, 0xd3, 0x42, 0x8a, 0xa3, 0x3d, 0x68, 0xfb, 0x44, 0x10, 0xe9, 0x5d, 0x47, 0x89, + 0x6d, 0x18, 0xb1, 0xa1, 0x64, 0x17, 0xce, 0x19, 0x14, 0xda, 0x85, 0xe6, 0x8c, 0x46, 0x51, 0xe2, + 0xda, 0x55, 0xb8, 0x0e, 0xce, 0x48, 0x1e, 0x8d, 0x6a, 0x58, 0x63, 0xd0, 0x40, 0x6b, 0x1f, 0x86, + 0x81, 0x0b, 0x0a, 0x8e, 0xca, 0xda, 0x87, 0x61, 0xa0, 0xaf, 0x60, 0x40, 0xc6, 0x1b, 0x79, 0xf3, + 0xee, 0xa2, 0x37, 0xf3, 0x3b, 0x1b, 0x14, 0x7a, 0x09, 0x20, 0x3f, 0x3f, 0xa6, 0x3e, 0x11, 0xd4, + 0xed, 0x2d, 0xda, 0xd0, 0x27, 0xa3, 0x1a, 0x2e, 0xe1, 0xd0, 0x37, 0xd0, 0xa4, 0x71, 0x2a, 0x6e, + 0xdc, 0xbe, 0x12, 0xe8, 0x1b, 0x81, 0x23, 0xc9, 0x94, 0xde, 0xab, 0x53, 0xb4, 0x0b, 0x8d, 0x69, + 0xc2, 0x98, 0xbb, 0xaa, 0x50, 0x8f, 0x0c, 0xea, 0x75, 0xc2, 0xd8, 0x11, 0x17, 0xe4, 0x22, 0x0a, + 0xf9, 0x6c, 0x54, 0xc3, 0x0a, 0x84, 0x9e, 0x83, 0xcd, 0x05, 0x11, 0xf4, 0x98, 0x5d, 0x26, 0xee, + 0x9a, 0x92, 0x58, 0x37, 0x12, 0xa7, 0xe6, 0x60, 0x54, 0xc3, 0x73, 0x14, 0x3a, 0x80, 0xbe, 0x22, + 0x4e, 0x19, 0x49, 0xf9, 0x2c, 0x11, 0xae, 0x53, 0xcd, 0x76, 0x21, 0x66, 0x00, 0xa3, 0x1a, 0xae, + 0x4a, 0xa0, 0x77, 0xe0, 0x14, 0xfa, 0x4e, 0xae, 0xa3, 0x48, 0x46, 0x6e, 0x5d, 0x69, 0x79, 0xb2, + 0xa0, 0x25, 0x3f, 0xcf, 0x43, 0xb8, 0x20, 0x87, 0x7e, 0x82, 0x9e, 0xe2, 0xe5, 0x18, 0x17, 0x55, + 0xcb, 0x08, 0xd3, 0x38, 0x11, 0xf4, 0xb4, 0x84, 0x18, 0xd5, 0x70, 0x45, 0x02, 0xbd, 0xce, 0x2f, + 0x64, 0xea, 0xcc, 0xdd, 0x50, 0x2a, 0xbe, 0x5c, 0xaa, 0xa2, 0x28, 0xc5, 0xaa, 0x8c, 0x8c, 0x4a, + 0x44, 0x89, 0xaf, 0x2b, 0x56, 0xd6, 0xe5, 0x66, 0x35, 0x2a, 0xef, 0xe7, 0x87, 0x45, 0x75, 0x56, + 0x25, 0xd0, 0x8f, 0xd0, 0x4b, 0x29, 0xcd, 0x8e, 0x7d, 0xca, 0x44, 0x28, 0x6e, 0xdc, 0x47, 0xd5, + 0x77, 0x77, 0x52, 0x3a, 0x93, 0x77, 0x28, 0x63, 0xbd, 0x73, 0xa8, 0x9f, 0x91, 0x00, 0xf5, 0xc1, + 0xfe, 0x38, 0x19, 0x1e, 0xbd, 0x39, 0x9e, 0x1c, 0x0d, 0x9d, 0x1a, 0xb2, 0xa1, 0x79, 0x34, 0x3e, + 0x39, 0xfb, 0xe4, 0x58, 0xa8, 0x07, 0x9d, 0x0f, 0xf8, 0xed, 0xf9, 0x87, 0xc9, 0xfb, 0x4f, 0xce, + 0x8a, 0xc4, 0xbd, 0x1e, 0x1d, 0x4c, 0x34, 0x59, 0x47, 0x0e, 0xf4, 0x14, 0x79, 0x30, 0x19, 0x9e, + 0x7f, 0xc0, 0x6f, 0x9d, 0x06, 0x5a, 0x83, 0xae, 0x06, 0x60, 0xc5, 0x68, 0x1e, 0xda, 0xd0, 0x9e, + 0x26, 0x4c, 0x50, 0x26, 0xbc, 0x18, 0xec, 0x22, 0x3b, 0x68, 0x0b, 0x3a, 0x31, 0x15, 0x44, 0x96, + 0x69, 0xde, 0xee, 0x0a, 0x1a, 0x0d, 0xc0, 0x16, 0x61, 0x4c, 0xb9, 0x20, 0x71, 0xaa, 0x7a, 0x55, + 0x77, 0xdf, 0x29, 0xdf, 0xe6, 0x2c, 0x8c, 0x29, 0x9e, 0x43, 0x64, 0xbf, 0x4b, 0xaf, 0xc2, 0xe3, + 0xa1, 0xea, 0x60, 0x3d, 0xac, 0x09, 0xef, 0x0d, 0xac, 0x2f, 0x94, 0x14, 0x7a, 0x0e, 0x1d, 0x1a, + 0xd1, 0x98, 0x32, 0xc1, 0x5d, 0x6b, 0xbb, 0x5e, 0x2e, 0xf4, 0x4a, 0xbf, 0xc3, 0x05, 0xcc, 0x7b, + 0x0c, 0x9b, 0xcb, 0x8a, 0xca, 0x1b, 0x43, 0xbf, 0xf2, 0x36, 0xe6, 0x6e, 0x58, 0x25, 0x37, 0x10, + 0x82, 0xc6, 0x94, 0x66, 0x22, 0xef, 0xb9, 0xea, 0x5b, 0xf2, 0x66, 0x84, 0xcf, 0x72, 0x7f, 0xd5, + 0xb7, 0x77, 0x06, 0xbd, 0x72, 0xa6, 0x1e, 0xa0, 0xad, 0x1c, 0xca, 0x7a, 0x35, 0x94, 0x5e, 0x04, + 0xdd, 0x52, 0x2f, 0xb9, 0x7b, 0x32, 0xf8, 0xaa, 0x39, 0x71, 0x77, 0x65, 0xbb, 0xbe, 0x63, 0x63, + 0x43, 0xa2, 0x67, 0xd0, 0x8e, 0x79, 0x70, 0x76, 0x93, 0xd2, 0x7c, 0x3a, 0x14, 0x1d, 0x4a, 0x46, + 0x62, 0xac, 0x8f, 0xb0, 0xc1, 0x78, 0x0c, 0xba, 0xa5, 0xc6, 0x78, 0x87, 0xb5, 0xb2, 0xbb, 0x2b, + 0xb7, 0x32, 0xff, 0x40, 0x7b, 0xbf, 0x03, 0xcc, 0xbb, 0xde, 0x1d, 0xe6, 0x9e, 0x42, 0x23, 0x37, + 0x75, 0x4f, 0xb6, 0x1b, 0xff, 0xc5, 0xfa, 0x95, 0xb6, 0xae, 0xfb, 0xfa, 0xff, 0x1d, 0xda, 0x1f, + 0x74, 0x22, 0xcd, 0x88, 0x7f, 0x5a, 0x5d, 0x16, 0xba, 0xfb, 0x6b, 0x85, 0xb4, 0x66, 0x17, 0xdb, + 0x83, 0x77, 0x0c, 0xed, 0x9c, 0x87, 0x1e, 0x43, 0x8b, 0xd3, 0xcf, 0x93, 0xeb, 0x38, 0x77, 0x32, + 0xa7, 0x8a, 0x7a, 0x94, 0xe9, 0xb0, 0x75, 0x3d, 0x4a, 0x5e, 0xa9, 0xa2, 0xd4, 0xb7, 0xf7, 0xa7, + 0x05, 0xbd, 0xf2, 0x18, 0x47, 0x03, 0x80, 0xb8, 0x98, 0xb7, 0xb9, 0x27, 0xab, 0xd5, 0x49, 0x8c, + 0x4b, 0x88, 0x07, 0xbf, 0xec, 0x2d, 0xe8, 0x84, 0xa6, 0xad, 0xe9, 0x5d, 0xa3, 0xa0, 0xbd, 0x3f, + 0x60, 0x7d, 0xa1, 0x39, 0xde, 0xf1, 0x6a, 0x1e, 0x6a, 0xf6, 0x6b, 0xe8, 0x87, 0x7c, 0x48, 0xa7, + 0x11, 0xc9, 0x88, 0x08, 0x13, 0xa6, 0x82, 0xd0, 0xc1, 0x55, 0xa6, 0x77, 0x00, 0x1d, 0x23, 0x8c, + 0xbe, 0x02, 0x08, 0xd9, 0xf4, 0x9c, 0x5d, 0xcb, 0xab, 0xe6, 0xd1, 0xb5, 0x43, 0x36, 0x9d, 0x28, + 0x46, 0x29, 0xf0, 0x2b, 0xe5, 0xc0, 0x7b, 0xbf, 0xc0, 0xfa, 0xc2, 0x92, 0x83, 0x5e, 0xc1, 0x1a, + 0xa7, 0xd1, 0xa5, 0xec, 0x37, 0x59, 0xac, 0xed, 0x5b, 0xd5, 0x99, 0x5c, 0x2d, 0xde, 0xdb, 0x68, + 0x19, 0x84, 0x2b, 0x96, 0xfc, 0xc6, 0x54, 0xc9, 0xf5, 0xb0, 0x26, 0xbc, 0x08, 0xd0, 0xe2, 0x6e, + 0x24, 0x17, 0x1c, 0xb5, 0x88, 0xdd, 0xdf, 0x0d, 0x35, 0x46, 0xbd, 0x25, 0x4a, 0xfc, 0x7f, 0x7b, + 0x4b, 0x94, 0xf8, 0xde, 0x5f, 0x16, 0xb4, 0xb4, 0x39, 0x99, 0x44, 0xca, 0xfc, 0x34, 0x09, 0x99, + 0x50, 0x17, 0xb1, 0x71, 0x41, 0xdf, 0xdb, 0x0c, 0x96, 0xb6, 0x75, 0x74, 0x08, 0x4e, 0xc8, 0x04, + 0xcd, 0x18, 0x89, 0x8e, 0x8c, 0xd6, 0x86, 0x0a, 0xcf, 0xe3, 0x62, 0x07, 0x50, 0xdb, 0xb5, 0x39, + 0xc5, 0x0b, 0x78, 0xef, 0x1d, 0xac, 0x56, 0x31, 0xf7, 0xfa, 0x78, 0xff, 0xfa, 0xdd, 0x86, 0xa6, + 0x5a, 0xa4, 0xbc, 0x01, 0xa0, 0xc5, 0xa5, 0x41, 0x36, 0x00, 0x9d, 0x6b, 0x3d, 0x6f, 0x1a, 0xd8, + 0x90, 0xde, 0x21, 0x6c, 0x2c, 0xd9, 0x10, 0xd0, 0x2e, 0x74, 0xf2, 0x97, 0x6b, 0x26, 0xd4, 0xc2, + 0xd3, 0x2e, 0x00, 0xdf, 0xbd, 0x82, 0x6e, 0xa9, 0x5b, 0xa8, 0x31, 0xce, 0x7c, 0x7a, 0x19, 0x32, + 0xea, 0x3b, 0x35, 0x39, 0x9e, 0x0f, 0xa3, 0x64, 0x7a, 0x95, 0x67, 0xc6, 0xb1, 0xe4, 0x78, 0x36, + 0x03, 0x66, 0xcc, 0x03, 0x67, 0x65, 0x5f, 0x40, 0x4b, 0x67, 0x0f, 0x1d, 0x42, 0x4f, 0x7f, 0x9d, + 0x8a, 0x8c, 0x92, 0x18, 0x2d, 0xcf, 0xee, 0xd6, 0x72, 0xb6, 0x57, 0xdb, 0xb1, 0xbe, 0xb7, 0xd0, + 0xb7, 0xd0, 0x38, 0x09, 0x59, 0x80, 0xaa, 0x2b, 0xe6, 0x56, 0x95, 0xf4, 0x6a, 0x87, 0xcf, 0x7e, + 0xde, 0x0d, 0x42, 0x31, 0xbb, 0xbe, 0x18, 0x4c, 0x93, 0x78, 0x6f, 0x76, 0x93, 0xd2, 0x2c, 0xa2, + 0x7e, 0x40, 0xb3, 0xbd, 0x4b, 0x72, 0x91, 0x85, 0xd3, 0x3d, 0xf5, 0xc3, 0xc4, 0xf7, 0xb4, 0xd8, + 0x45, 0x4b, 0x91, 0x2f, 0xfe, 0x09, 0x00, 0x00, 0xff, 0xff, 0xaf, 0xae, 0x6f, 0x88, 0x57, 0x0d, + 0x00, 0x00, } diff --git a/protos/gossip/message.proto b/protos/gossip/message.proto index 970142c6dc6..96727c28004 100644 --- a/protos/gossip/message.proto +++ b/protos/gossip/message.proto @@ -13,7 +13,13 @@ service Gossip { // Ping is used to probe a remote peer's aliveness rpc Ping (Empty) returns (Empty) {} +} +// GossipMessage contains a marshalled +// GossipMessage and a signature over it. +message SignedGossipMessage { + bytes payload = 1; + bytes signature = 2; } // GossipMessage defines the message sent in a gossip network