|
|
@@ -54,11 +54,11 @@ var (
|
|
|
Name: "wormhole_p2p_heartbeats_sent_total",
|
|
|
Help: "Total number of p2p heartbeats sent",
|
|
|
})
|
|
|
- p2pMessagesSent = promauto.NewCounter(
|
|
|
+ p2pMessagesSent = promauto.NewCounterVec(
|
|
|
prometheus.CounterOpts{
|
|
|
Name: "wormhole_p2p_broadcast_messages_sent_total",
|
|
|
Help: "Total number of p2p pubsub broadcast messages sent",
|
|
|
- })
|
|
|
+ }, []string{"type"})
|
|
|
p2pMessagesReceived = promauto.NewCounterVec(
|
|
|
prometheus.CounterOpts{
|
|
|
Name: "wormhole_p2p_broadcast_messages_received_total",
|
|
|
@@ -110,6 +110,7 @@ type Components struct {
|
|
|
// is only accessed by a single routine at any given time in a running Guardian.
|
|
|
ProtectedHostByGuardianKeyLock sync.Mutex
|
|
|
// WarnChannelOverflow: If true, errors due to overflowing channels will produce logger.Warn
|
|
|
+ // WARNING: This should not be enabled in production. It is only used in node tests to watch for overflows.
|
|
|
WarnChannelOverflow bool
|
|
|
// SignedHeartbeatLogLevel is the log level at which SignedHeartbeatReceived events will be logged.
|
|
|
SignedHeartbeatLogLevel zapcore.Level
|
|
|
@@ -301,12 +302,25 @@ func Run(params *RunParams) func(ctx context.Context) error {
|
|
|
}
|
|
|
|
|
|
return func(ctx context.Context) error {
|
|
|
+ p2pMessagesSent.WithLabelValues("control").Add(0)
|
|
|
+ p2pMessagesSent.WithLabelValues("attestation").Add(0)
|
|
|
+ p2pMessagesSent.WithLabelValues("vaa").Add(0)
|
|
|
p2pReceiveChannelOverflow.WithLabelValues("observation").Add(0)
|
|
|
p2pReceiveChannelOverflow.WithLabelValues("signed_vaa_with_quorum").Add(0)
|
|
|
p2pReceiveChannelOverflow.WithLabelValues("signed_observation_request").Add(0)
|
|
|
|
|
|
logger := supervisor.Logger(ctx)
|
|
|
|
|
|
+ // Evaluate the gossip cutover time. If it has passed, then the flag will be set to make us publish on the new topics.
|
|
|
+ // If not, a routine will be started to wait for that time before starting to publish on the new topics.
|
|
|
+ cutoverErr := evaluateGossipCutOver(logger, params.networkID)
|
|
|
+ if cutoverErr != nil {
|
|
|
+ panic(cutoverErr)
|
|
|
+ }
|
|
|
+
|
|
|
+ // If the cutover has not happened yet, we need to join and subscribe to the VAA topic because it is also the old topic.
|
|
|
+ needOldTopic := !GossipCutoverComplete()
|
|
|
+
|
|
|
defer func() {
|
|
|
// TODO: Right now we're canceling the root context because it used to be the case that libp2p cannot be cleanly restarted.
|
|
|
// But that seems to no longer be the case. We may want to revisit this. See (https://github.com/libp2p/go-libp2p/issues/992) for background.
|
|
|
@@ -330,8 +344,6 @@ func Run(params *RunParams) func(ctx context.Context) error {
|
|
|
panic(err)
|
|
|
}
|
|
|
|
|
|
- topic := fmt.Sprintf("%s/%s", params.networkID, "broadcast")
|
|
|
-
|
|
|
bootstrappers, bootstrapNode := BootstrapAddrs(logger, params.bootstrapPeers, h.ID())
|
|
|
|
|
|
if bootstrapNode {
|
|
|
@@ -342,7 +354,7 @@ func Run(params *RunParams) func(ctx context.Context) error {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- logger.Info("Subscribing pubsub topic", zap.String("topic", topic))
|
|
|
+ logger.Info("connecting to pubsub")
|
|
|
ourTracer := &traceHandler{}
|
|
|
ps, err := pubsub.NewGossipSub(ctx, h,
|
|
|
pubsub.WithValidateQueueSize(P2P_VALIDATE_QUEUE_SIZE),
|
|
|
@@ -355,24 +367,84 @@ func Run(params *RunParams) func(ctx context.Context) error {
|
|
|
panic(err)
|
|
|
}
|
|
|
|
|
|
- th, err := ps.Join(topic)
|
|
|
- if err != nil {
|
|
|
- return fmt.Errorf("failed to join topic: %w", err)
|
|
|
+ // These will only be non-nil if the application plans to listen for or publish to that topic.
|
|
|
+ var controlPubsubTopic, attestationPubsubTopic, vaaPubsubTopic *pubsub.Topic
|
|
|
+ var controlSubscription, attestationSubscription, vaaSubscription *pubsub.Subscription
|
|
|
+
|
|
|
+ // Set up the control channel. ////////////////////////////////////////////////////////////////////
|
|
|
+ if params.nodeName != "" || params.gossipControlSendC != nil || params.obsvReqSendC != nil || params.obsvReqRecvC != nil || params.signedGovCfgRecvC != nil || params.signedGovStatusRecvC != nil {
|
|
|
+ controlTopic := fmt.Sprintf("%s/%s", params.networkID, "control")
|
|
|
+ logger.Info("joining the control topic", zap.String("topic", controlTopic))
|
|
|
+ controlPubsubTopic, err = ps.Join(controlTopic)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("failed to join the control topic: %w", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ defer func() {
|
|
|
+ if err := controlPubsubTopic.Close(); err != nil && !errors.Is(err, context.Canceled) {
|
|
|
+ logger.Error("Error closing the control topic", zap.Error(err))
|
|
|
+ }
|
|
|
+ }()
|
|
|
+
|
|
|
+ if params.obsvReqRecvC != nil || params.signedGovCfgRecvC != nil || params.signedGovStatusRecvC != nil {
|
|
|
+ logger.Info("subscribing to the control topic", zap.String("topic", controlTopic))
|
|
|
+ controlSubscription, err = controlPubsubTopic.Subscribe(pubsub.WithBufferSize(P2P_SUBSCRIPTION_BUFFER_SIZE))
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("failed to subscribe to the control topic: %w", err)
|
|
|
+ }
|
|
|
+ defer controlSubscription.Cancel()
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- defer func() {
|
|
|
- if err := th.Close(); err != nil && !errors.Is(err, context.Canceled) {
|
|
|
- logger.Error("Error closing the topic", zap.Error(err))
|
|
|
+ // Set up the attestation channel. ////////////////////////////////////////////////////////////////////
|
|
|
+ if params.gossipAttestationSendC != nil || params.obsvRecvC != nil {
|
|
|
+ attestationTopic := fmt.Sprintf("%s/%s", params.networkID, "attestation")
|
|
|
+ logger.Info("joining the attestation topic", zap.String("topic", attestationTopic))
|
|
|
+ attestationPubsubTopic, err = ps.Join(attestationTopic)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("failed to join the attestation topic: %w", err)
|
|
|
}
|
|
|
- }()
|
|
|
|
|
|
- // Increase the buffer size to prevent failed delivery
|
|
|
- // to slower subscribers
|
|
|
- sub, err := th.Subscribe(pubsub.WithBufferSize(P2P_SUBSCRIPTION_BUFFER_SIZE))
|
|
|
- if err != nil {
|
|
|
- return fmt.Errorf("failed to subscribe topic: %w", err)
|
|
|
+ defer func() {
|
|
|
+ if err := attestationPubsubTopic.Close(); err != nil && !errors.Is(err, context.Canceled) {
|
|
|
+ logger.Error("Error closing the attestation topic", zap.Error(err))
|
|
|
+ }
|
|
|
+ }()
|
|
|
+
|
|
|
+ if params.obsvRecvC != nil {
|
|
|
+ logger.Info("subscribing to the attestation topic", zap.String("topic", attestationTopic))
|
|
|
+ attestationSubscription, err = attestationPubsubTopic.Subscribe(pubsub.WithBufferSize(P2P_SUBSCRIPTION_BUFFER_SIZE))
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("failed to subscribe to the attestation topic: %w", err)
|
|
|
+ }
|
|
|
+ defer attestationSubscription.Cancel()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set up the VAA channel. ////////////////////////////////////////////////////////////////////
|
|
|
+ if params.gossipVaaSendC != nil || params.signedIncomingVaaRecvC != nil || needOldTopic {
|
|
|
+ vaaTopic := fmt.Sprintf("%s/%s", params.networkID, "broadcast")
|
|
|
+ logger.Info("joining the vaa topic", zap.String("topic", vaaTopic))
|
|
|
+ vaaPubsubTopic, err = ps.Join(vaaTopic)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("failed to join the vaa topic: %w", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ defer func() {
|
|
|
+ if err := vaaPubsubTopic.Close(); err != nil && !errors.Is(err, context.Canceled) {
|
|
|
+ logger.Error("Error closing the vaa topic", zap.Error(err))
|
|
|
+ }
|
|
|
+ }()
|
|
|
+
|
|
|
+ if params.signedIncomingVaaRecvC != nil || needOldTopic {
|
|
|
+ logger.Info("subscribing to the vaa topic", zap.String("topic", vaaTopic))
|
|
|
+ vaaSubscription, err = vaaPubsubTopic.Subscribe(pubsub.WithBufferSize(P2P_SUBSCRIPTION_BUFFER_SIZE))
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("failed to subscribe to the vaa topic: %w", err)
|
|
|
+ }
|
|
|
+ defer vaaSubscription.Cancel()
|
|
|
+ }
|
|
|
}
|
|
|
- defer sub.Cancel()
|
|
|
|
|
|
// Make sure we connect to at least 1 bootstrap node (this is particularly important in a local devnet and CI
|
|
|
// as peer discovery can take a long time).
|
|
|
@@ -426,119 +498,169 @@ func Run(params *RunParams) func(ctx context.Context) error {
|
|
|
}
|
|
|
}()
|
|
|
|
|
|
- go func() {
|
|
|
- // Disable heartbeat when no node name is provided (spy mode)
|
|
|
- if params.nodeName == "" {
|
|
|
- return
|
|
|
- }
|
|
|
- ourAddr := ethcrypto.PubkeyToAddress(params.gk.PublicKey)
|
|
|
+ // Start up heartbeating if it is enabled.
|
|
|
+ if params.nodeName != "" {
|
|
|
+ go func() {
|
|
|
+ ourAddr := ethcrypto.PubkeyToAddress(params.gk.PublicKey)
|
|
|
|
|
|
- ctr := int64(0)
|
|
|
- // Guardians should send out their first heartbeat immediately to speed up test runs.
|
|
|
- // But we also want to wait a little bit such that network connections can be established by then.
|
|
|
- timer := time.NewTimer(time.Second * 2)
|
|
|
- defer timer.Stop()
|
|
|
+ ctr := int64(0)
|
|
|
+ // Guardians should send out their first heartbeat immediately to speed up test runs.
|
|
|
+ // But we also want to wait a little bit such that network connections can be established by then.
|
|
|
+ timer := time.NewTimer(time.Second * 2)
|
|
|
+ defer timer.Stop()
|
|
|
|
|
|
- for {
|
|
|
- select {
|
|
|
- case <-ctx.Done():
|
|
|
- return
|
|
|
- case <-timer.C:
|
|
|
- timer.Reset(15 * time.Second)
|
|
|
-
|
|
|
- // create a heartbeat
|
|
|
- b := func() []byte {
|
|
|
- DefaultRegistry.mu.Lock()
|
|
|
- defer DefaultRegistry.mu.Unlock()
|
|
|
- networks := make([]*gossipv1.Heartbeat_Network, 0, len(DefaultRegistry.networkStats))
|
|
|
- for _, v := range DefaultRegistry.networkStats {
|
|
|
- errCtr := DefaultRegistry.GetErrorCount(vaa.ChainID(v.Id))
|
|
|
- v.ErrorCount = errCtr
|
|
|
- networks = append(networks, v)
|
|
|
- }
|
|
|
+ for {
|
|
|
+ select {
|
|
|
+ case <-ctx.Done():
|
|
|
+ return
|
|
|
+ case <-timer.C:
|
|
|
+ timer.Reset(15 * time.Second)
|
|
|
+
|
|
|
+ // create a heartbeat
|
|
|
+ b := func() []byte {
|
|
|
+ DefaultRegistry.mu.Lock()
|
|
|
+ defer DefaultRegistry.mu.Unlock()
|
|
|
+ networks := make([]*gossipv1.Heartbeat_Network, 0, len(DefaultRegistry.networkStats))
|
|
|
+ for _, v := range DefaultRegistry.networkStats {
|
|
|
+ errCtr := DefaultRegistry.GetErrorCount(vaa.ChainID(v.Id))
|
|
|
+ v.ErrorCount = errCtr
|
|
|
+ networks = append(networks, v)
|
|
|
+ }
|
|
|
|
|
|
- features := make([]string, 0)
|
|
|
- if params.gov != nil {
|
|
|
- if params.gov.IsFlowCancelEnabled() {
|
|
|
- features = append(features, "governor:fc")
|
|
|
- } else {
|
|
|
- features = append(features, "governor")
|
|
|
+ features := make([]string, 0)
|
|
|
+ if params.gov != nil {
|
|
|
+ if params.gov.IsFlowCancelEnabled() {
|
|
|
+ features = append(features, "governor:fc")
|
|
|
+ } else {
|
|
|
+ features = append(features, "governor")
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- if params.acct != nil {
|
|
|
- features = append(features, params.acct.FeatureString())
|
|
|
- }
|
|
|
- if params.ibcFeaturesFunc != nil {
|
|
|
- ibcFlags := params.ibcFeaturesFunc()
|
|
|
- if ibcFlags != "" {
|
|
|
- features = append(features, ibcFlags)
|
|
|
+ if params.acct != nil {
|
|
|
+ features = append(features, params.acct.FeatureString())
|
|
|
+ }
|
|
|
+ if params.ibcFeaturesFunc != nil {
|
|
|
+ ibcFlags := params.ibcFeaturesFunc()
|
|
|
+ if ibcFlags != "" {
|
|
|
+ features = append(features, ibcFlags)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if params.gatewayRelayerEnabled {
|
|
|
+ features = append(features, "gwrelayer")
|
|
|
+ }
|
|
|
+ if params.ccqEnabled {
|
|
|
+ features = append(features, "ccq")
|
|
|
}
|
|
|
- }
|
|
|
- if params.gatewayRelayerEnabled {
|
|
|
- features = append(features, "gwrelayer")
|
|
|
- }
|
|
|
- if params.ccqEnabled {
|
|
|
- features = append(features, "ccq")
|
|
|
- }
|
|
|
|
|
|
- heartbeat := &gossipv1.Heartbeat{
|
|
|
- NodeName: params.nodeName,
|
|
|
- Counter: ctr,
|
|
|
- Timestamp: time.Now().UnixNano(),
|
|
|
- Networks: networks,
|
|
|
- Version: version.Version(),
|
|
|
- GuardianAddr: ourAddr.String(),
|
|
|
- BootTimestamp: bootTime.UnixNano(),
|
|
|
- Features: features,
|
|
|
- }
|
|
|
+ heartbeat := &gossipv1.Heartbeat{
|
|
|
+ NodeName: params.nodeName,
|
|
|
+ Counter: ctr,
|
|
|
+ Timestamp: time.Now().UnixNano(),
|
|
|
+ Networks: networks,
|
|
|
+ Version: version.Version(),
|
|
|
+ GuardianAddr: ourAddr.String(),
|
|
|
+ BootTimestamp: bootTime.UnixNano(),
|
|
|
+ Features: features,
|
|
|
+ }
|
|
|
|
|
|
- if params.components.P2PIDInHeartbeat {
|
|
|
- heartbeat.P2PNodeId = nodeIdBytes
|
|
|
- }
|
|
|
+ if params.components.P2PIDInHeartbeat {
|
|
|
+ heartbeat.P2PNodeId = nodeIdBytes
|
|
|
+ }
|
|
|
|
|
|
- if err := params.gst.SetHeartbeat(ourAddr, h.ID(), heartbeat); err != nil {
|
|
|
- panic(err)
|
|
|
- }
|
|
|
- collectNodeMetrics(ourAddr, h.ID(), heartbeat)
|
|
|
+ if err := params.gst.SetHeartbeat(ourAddr, h.ID(), heartbeat); err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+ collectNodeMetrics(ourAddr, h.ID(), heartbeat)
|
|
|
|
|
|
- if params.gov != nil {
|
|
|
- params.gov.CollectMetrics(heartbeat, params.gossipSendC, params.gk, ourAddr)
|
|
|
- }
|
|
|
+ if params.gov != nil {
|
|
|
+ params.gov.CollectMetrics(heartbeat, params.gossipControlSendC, params.gk, ourAddr)
|
|
|
+ }
|
|
|
|
|
|
- msg := gossipv1.GossipMessage{
|
|
|
- Message: &gossipv1.GossipMessage_SignedHeartbeat{
|
|
|
- SignedHeartbeat: createSignedHeartbeat(params.gk, heartbeat),
|
|
|
- },
|
|
|
- }
|
|
|
+ msg := gossipv1.GossipMessage{
|
|
|
+ Message: &gossipv1.GossipMessage_SignedHeartbeat{
|
|
|
+ SignedHeartbeat: createSignedHeartbeat(params.gk, heartbeat),
|
|
|
+ },
|
|
|
+ }
|
|
|
|
|
|
- b, err := proto.Marshal(&msg)
|
|
|
- if err != nil {
|
|
|
- panic(err)
|
|
|
+ b, err := proto.Marshal(&msg)
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+ return b
|
|
|
+ }()
|
|
|
+
|
|
|
+ if GossipCutoverComplete() {
|
|
|
+ if controlPubsubTopic == nil {
|
|
|
+ panic("controlPubsubTopic should not be nil when nodeName is set")
|
|
|
+ }
|
|
|
+ err = controlPubsubTopic.Publish(ctx, b)
|
|
|
+ p2pMessagesSent.WithLabelValues("control").Inc()
|
|
|
+ if err != nil {
|
|
|
+ logger.Warn("failed to publish heartbeat message", zap.Error(err))
|
|
|
+ }
|
|
|
+ } else if vaaPubsubTopic != nil {
|
|
|
+ err = vaaPubsubTopic.Publish(ctx, b)
|
|
|
+ p2pMessagesSent.WithLabelValues("old_control").Inc()
|
|
|
+ if err != nil {
|
|
|
+ logger.Warn("failed to publish heartbeat message to old topic", zap.Error(err))
|
|
|
+ }
|
|
|
}
|
|
|
- return b
|
|
|
- }()
|
|
|
|
|
|
- err = th.Publish(ctx, b)
|
|
|
- if err != nil {
|
|
|
- logger.Warn("failed to publish heartbeat message", zap.Error(err))
|
|
|
+ p2pHeartbeatsSent.Inc()
|
|
|
+ ctr += 1
|
|
|
}
|
|
|
-
|
|
|
- p2pHeartbeatsSent.Inc()
|
|
|
- ctr += 1
|
|
|
}
|
|
|
- }
|
|
|
- }()
|
|
|
+ }()
|
|
|
+ }
|
|
|
|
|
|
+ // This routine processes messages received from the internal channels and publishes them to gossip. ///////////////////
|
|
|
+ // NOTE: The go specification says that it is safe to receive on a nil channel, it just blocks forever.
|
|
|
go func() {
|
|
|
for {
|
|
|
select {
|
|
|
case <-ctx.Done():
|
|
|
return
|
|
|
- case msg := <-params.gossipSendC:
|
|
|
- err := th.Publish(ctx, msg)
|
|
|
- p2pMessagesSent.Inc()
|
|
|
+ case msg := <-params.gossipControlSendC:
|
|
|
+ if GossipCutoverComplete() {
|
|
|
+ if controlPubsubTopic == nil {
|
|
|
+ panic("controlPubsubTopic should not be nil when gossipControlSendC is set")
|
|
|
+ }
|
|
|
+ err := controlPubsubTopic.Publish(ctx, msg)
|
|
|
+ p2pMessagesSent.WithLabelValues("control").Inc()
|
|
|
+ if err != nil {
|
|
|
+ logger.Error("failed to publish message from control queue", zap.Error(err))
|
|
|
+ }
|
|
|
+ } else if vaaPubsubTopic != nil {
|
|
|
+ err := vaaPubsubTopic.Publish(ctx, msg)
|
|
|
+ p2pMessagesSent.WithLabelValues("old_control").Inc()
|
|
|
+ if err != nil {
|
|
|
+ logger.Error("failed to publish message from control queue to old topic", zap.Error(err))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case msg := <-params.gossipAttestationSendC:
|
|
|
+ if GossipCutoverComplete() {
|
|
|
+ if attestationPubsubTopic == nil {
|
|
|
+ panic("attestationPubsubTopic should not be nil when gossipAttestationSendC is set")
|
|
|
+ }
|
|
|
+ err := attestationPubsubTopic.Publish(ctx, msg)
|
|
|
+ p2pMessagesSent.WithLabelValues("attestation").Inc()
|
|
|
+ if err != nil {
|
|
|
+ logger.Error("failed to publish message from attestation queue", zap.Error(err))
|
|
|
+ }
|
|
|
+ } else if vaaPubsubTopic != nil {
|
|
|
+ err := vaaPubsubTopic.Publish(ctx, msg)
|
|
|
+ p2pMessagesSent.WithLabelValues("old_attestation").Inc()
|
|
|
+ if err != nil {
|
|
|
+ logger.Error("failed to publish message from attestation queue to old topic", zap.Error(err))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case msg := <-params.gossipVaaSendC:
|
|
|
+ if vaaPubsubTopic == nil {
|
|
|
+ panic("vaaPubsubTopic should not be nil when gossipVaaSendC is set")
|
|
|
+ }
|
|
|
+ err := vaaPubsubTopic.Publish(ctx, msg)
|
|
|
+ p2pMessagesSent.WithLabelValues("vaa").Inc()
|
|
|
if err != nil {
|
|
|
- logger.Error("failed to publish message from queue", zap.Error(err))
|
|
|
+ logger.Error("failed to publish message from vaa queue", zap.Error(err))
|
|
|
}
|
|
|
case msg := <-params.obsvReqSendC:
|
|
|
b, err := proto.Marshal(msg)
|
|
|
@@ -569,193 +691,429 @@ func Run(params *RunParams) func(ctx context.Context) error {
|
|
|
}
|
|
|
|
|
|
// Send to local observation request queue (the loopback message is ignored)
|
|
|
- if params.obsvReqC != nil {
|
|
|
- params.obsvReqC <- msg
|
|
|
+ if params.obsvReqRecvC != nil {
|
|
|
+ params.obsvReqRecvC <- msg
|
|
|
}
|
|
|
|
|
|
- err = th.Publish(ctx, b)
|
|
|
- p2pMessagesSent.Inc()
|
|
|
- if err != nil {
|
|
|
- logger.Error("failed to publish observation request", zap.Error(err))
|
|
|
- } else {
|
|
|
- logger.Info("published signed observation request", zap.Any("signed_observation_request", sReq))
|
|
|
+ if GossipCutoverComplete() {
|
|
|
+ if controlPubsubTopic == nil {
|
|
|
+ panic("controlPubsubTopic should not be nil when obsvReqSendC is set")
|
|
|
+ }
|
|
|
+ err = controlPubsubTopic.Publish(ctx, b)
|
|
|
+ p2pMessagesSent.WithLabelValues("control").Inc()
|
|
|
+ if err != nil {
|
|
|
+ logger.Error("failed to publish observation request", zap.Error(err))
|
|
|
+ } else {
|
|
|
+ logger.Info("published signed observation request", zap.Any("signed_observation_request", sReq))
|
|
|
+ }
|
|
|
+ } else if vaaPubsubTopic != nil {
|
|
|
+ err = vaaPubsubTopic.Publish(ctx, b)
|
|
|
+ p2pMessagesSent.WithLabelValues("old_control").Inc()
|
|
|
+ if err != nil {
|
|
|
+ logger.Error("failed to publish observation request to old topic", zap.Error(err))
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}()
|
|
|
|
|
|
- for {
|
|
|
- envelope, err := sub.Next(ctx) // Note: sub.Next(ctx) will return an error once ctx is canceled
|
|
|
- if err != nil {
|
|
|
- return fmt.Errorf("failed to receive pubsub message: %w", err)
|
|
|
- }
|
|
|
+ errC := make(chan error)
|
|
|
|
|
|
- var msg gossipv1.GossipMessage
|
|
|
- err = proto.Unmarshal(envelope.Data, &msg)
|
|
|
- if err != nil {
|
|
|
- logger.Info("received invalid message",
|
|
|
- zap.Binary("data", envelope.Data),
|
|
|
- zap.String("from", envelope.GetFrom().String()))
|
|
|
- p2pMessagesReceived.WithLabelValues("invalid").Inc()
|
|
|
- continue
|
|
|
- }
|
|
|
+ // This routine processes control messages received from gossip. //////////////////////////////////////////////
|
|
|
+ if controlSubscription != nil {
|
|
|
+ go func() {
|
|
|
+ for {
|
|
|
+ envelope, err := controlSubscription.Next(ctx) // Note: sub.Next(ctx) will return an error once ctx is canceled
|
|
|
+ if err != nil {
|
|
|
+ errC <- fmt.Errorf("failed to receive pubsub message on control topic: %w", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
- if envelope.GetFrom() == h.ID() {
|
|
|
- if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
- logger.Debug("received message from ourselves, ignoring", zap.Any("payload", msg.Message))
|
|
|
- }
|
|
|
- p2pMessagesReceived.WithLabelValues("loopback").Inc()
|
|
|
- continue
|
|
|
- }
|
|
|
+ var msg gossipv1.GossipMessage
|
|
|
+ err = proto.Unmarshal(envelope.Data, &msg)
|
|
|
+ if err != nil {
|
|
|
+ logger.Info("received invalid message on control topic",
|
|
|
+ zap.Binary("data", envelope.Data),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
+ p2pMessagesReceived.WithLabelValues("invalid").Inc()
|
|
|
+ continue
|
|
|
+ }
|
|
|
|
|
|
- if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
- logger.Debug("received message",
|
|
|
- zap.Any("payload", msg.Message),
|
|
|
- zap.Binary("raw", envelope.Data),
|
|
|
- zap.String("from", envelope.GetFrom().String()))
|
|
|
- }
|
|
|
+ if envelope.GetFrom() == h.ID() {
|
|
|
+ if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
+ logger.Debug("received message from ourselves on control topic, ignoring", zap.Any("payload", msg.Message))
|
|
|
+ }
|
|
|
+ p2pMessagesReceived.WithLabelValues("loopback").Inc()
|
|
|
+ continue
|
|
|
+ }
|
|
|
|
|
|
- switch m := msg.Message.(type) {
|
|
|
- case *gossipv1.GossipMessage_SignedHeartbeat:
|
|
|
- s := m.SignedHeartbeat
|
|
|
- gs := params.gst.Get()
|
|
|
- if gs == nil {
|
|
|
- // No valid guardian set yet - dropping heartbeat
|
|
|
- logger.Log(params.components.SignedHeartbeatLogLevel, "skipping heartbeat - no guardian set",
|
|
|
- zap.Any("value", s),
|
|
|
- zap.String("from", envelope.GetFrom().String()))
|
|
|
- break
|
|
|
- }
|
|
|
- if heartbeat, err := processSignedHeartbeat(envelope.GetFrom(), s, gs, params.gst, params.disableHeartbeatVerify); err != nil {
|
|
|
- p2pMessagesReceived.WithLabelValues("invalid_heartbeat").Inc()
|
|
|
- logger.Log(params.components.SignedHeartbeatLogLevel, "invalid signed heartbeat received",
|
|
|
- zap.Error(err),
|
|
|
- zap.Any("payload", msg.Message),
|
|
|
- zap.Any("value", s),
|
|
|
- zap.Binary("raw", envelope.Data),
|
|
|
- zap.String("from", envelope.GetFrom().String()))
|
|
|
- } else {
|
|
|
- p2pMessagesReceived.WithLabelValues("valid_heartbeat").Inc()
|
|
|
- logger.Log(params.components.SignedHeartbeatLogLevel, "valid signed heartbeat received",
|
|
|
- zap.Any("value", heartbeat),
|
|
|
- zap.String("from", envelope.GetFrom().String()))
|
|
|
-
|
|
|
- func() {
|
|
|
- if len(heartbeat.P2PNodeId) != 0 {
|
|
|
- params.components.ProtectedHostByGuardianKeyLock.Lock()
|
|
|
- defer params.components.ProtectedHostByGuardianKeyLock.Unlock()
|
|
|
- var peerId peer.ID
|
|
|
- if err = peerId.Unmarshal(heartbeat.P2PNodeId); err != nil {
|
|
|
- logger.Error("p2p_node_id_in_heartbeat_invalid",
|
|
|
- zap.Any("payload", msg.Message),
|
|
|
- zap.Any("value", s),
|
|
|
- zap.Binary("raw", envelope.Data),
|
|
|
- zap.String("from", envelope.GetFrom().String()))
|
|
|
- } else {
|
|
|
- guardianAddr := eth_common.BytesToAddress(s.GuardianAddr)
|
|
|
- if params.gk == nil || guardianAddr != ethcrypto.PubkeyToAddress(params.gk.PublicKey) {
|
|
|
- prevPeerId, ok := params.components.ProtectedHostByGuardianKey[guardianAddr]
|
|
|
- if ok {
|
|
|
- if prevPeerId != peerId {
|
|
|
- logger.Info("p2p_guardian_peer_changed",
|
|
|
- zap.String("guardian_addr", guardianAddr.String()),
|
|
|
- zap.String("prevPeerId", prevPeerId.String()),
|
|
|
- zap.String("newPeerId", peerId.String()),
|
|
|
- )
|
|
|
- params.components.ConnMgr.Unprotect(prevPeerId, "heartbeat")
|
|
|
- params.components.ConnMgr.Protect(peerId, "heartbeat")
|
|
|
- params.components.ProtectedHostByGuardianKey[guardianAddr] = peerId
|
|
|
- }
|
|
|
+ if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
+ logger.Debug("received message on control topic",
|
|
|
+ zap.Any("payload", msg.Message),
|
|
|
+ zap.Binary("raw", envelope.Data),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
+ }
|
|
|
+
|
|
|
+ switch m := msg.Message.(type) {
|
|
|
+ case *gossipv1.GossipMessage_SignedHeartbeat:
|
|
|
+ s := m.SignedHeartbeat
|
|
|
+ gs := params.gst.Get()
|
|
|
+ if gs == nil {
|
|
|
+ // No valid guardian set yet - dropping heartbeat
|
|
|
+ logger.Log(params.components.SignedHeartbeatLogLevel, "skipping heartbeat - no guardian set",
|
|
|
+ zap.Any("value", s),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
+ break
|
|
|
+ }
|
|
|
+ if heartbeat, err := processSignedHeartbeat(envelope.GetFrom(), s, gs, params.gst, params.disableHeartbeatVerify); err != nil {
|
|
|
+ p2pMessagesReceived.WithLabelValues("invalid_heartbeat").Inc()
|
|
|
+ logger.Log(params.components.SignedHeartbeatLogLevel, "invalid signed heartbeat received",
|
|
|
+ zap.Error(err),
|
|
|
+ zap.Any("payload", msg.Message),
|
|
|
+ zap.Any("value", s),
|
|
|
+ zap.Binary("raw", envelope.Data),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
+ } else {
|
|
|
+ p2pMessagesReceived.WithLabelValues("valid_heartbeat").Inc()
|
|
|
+ logger.Log(params.components.SignedHeartbeatLogLevel, "valid signed heartbeat received",
|
|
|
+ zap.Any("value", heartbeat),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
+
|
|
|
+ func() {
|
|
|
+ if len(heartbeat.P2PNodeId) != 0 {
|
|
|
+ params.components.ProtectedHostByGuardianKeyLock.Lock()
|
|
|
+ defer params.components.ProtectedHostByGuardianKeyLock.Unlock()
|
|
|
+ var peerId peer.ID
|
|
|
+ if err = peerId.Unmarshal(heartbeat.P2PNodeId); err != nil {
|
|
|
+ logger.Error("p2p_node_id_in_heartbeat_invalid",
|
|
|
+ zap.Any("payload", msg.Message),
|
|
|
+ zap.Any("value", s),
|
|
|
+ zap.Binary("raw", envelope.Data),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
} else {
|
|
|
- params.components.ConnMgr.Protect(peerId, "heartbeat")
|
|
|
- params.components.ProtectedHostByGuardianKey[guardianAddr] = peerId
|
|
|
+ guardianAddr := eth_common.BytesToAddress(s.GuardianAddr)
|
|
|
+ if params.gk == nil || guardianAddr != ethcrypto.PubkeyToAddress(params.gk.PublicKey) {
|
|
|
+ prevPeerId, ok := params.components.ProtectedHostByGuardianKey[guardianAddr]
|
|
|
+ if ok {
|
|
|
+ if prevPeerId != peerId {
|
|
|
+ logger.Info("p2p_guardian_peer_changed",
|
|
|
+ zap.String("guardian_addr", guardianAddr.String()),
|
|
|
+ zap.String("prevPeerId", prevPeerId.String()),
|
|
|
+ zap.String("newPeerId", peerId.String()),
|
|
|
+ )
|
|
|
+ params.components.ConnMgr.Unprotect(prevPeerId, "heartbeat")
|
|
|
+ params.components.ConnMgr.Protect(peerId, "heartbeat")
|
|
|
+ params.components.ProtectedHostByGuardianKey[guardianAddr] = peerId
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ params.components.ConnMgr.Protect(peerId, "heartbeat")
|
|
|
+ params.components.ProtectedHostByGuardianKey[guardianAddr] = peerId
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
+ logger.Debug("p2p_node_id_not_in_heartbeat", zap.Error(err), zap.Any("payload", heartbeat.NodeName))
|
|
|
}
|
|
|
}
|
|
|
+ }()
|
|
|
+ }
|
|
|
+ case *gossipv1.GossipMessage_SignedObservationRequest:
|
|
|
+ if params.obsvReqRecvC != nil {
|
|
|
+ s := m.SignedObservationRequest
|
|
|
+ gs := params.gst.Get()
|
|
|
+ if gs == nil {
|
|
|
+ if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
+ logger.Debug("dropping SignedObservationRequest - no guardian set", zap.Any("value", s), zap.String("from", envelope.GetFrom().String()))
|
|
|
+ }
|
|
|
+ break
|
|
|
}
|
|
|
- } else {
|
|
|
- if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
- logger.Debug("p2p_node_id_not_in_heartbeat", zap.Error(err), zap.Any("payload", heartbeat.NodeName))
|
|
|
+ r, err := processSignedObservationRequest(s, gs)
|
|
|
+ if err != nil {
|
|
|
+ p2pMessagesReceived.WithLabelValues("invalid_signed_observation_request").Inc()
|
|
|
+ if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
+ logger.Debug("invalid signed observation request received",
|
|
|
+ zap.Error(err),
|
|
|
+ zap.Any("payload", msg.Message),
|
|
|
+ zap.Any("value", s),
|
|
|
+ zap.Binary("raw", envelope.Data),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
+ logger.Debug("valid signed observation request received", zap.Any("value", r), zap.String("from", envelope.GetFrom().String()))
|
|
|
+ }
|
|
|
+
|
|
|
+ select {
|
|
|
+ case params.obsvReqRecvC <- r:
|
|
|
+ p2pMessagesReceived.WithLabelValues("signed_observation_request").Inc()
|
|
|
+ default:
|
|
|
+ p2pReceiveChannelOverflow.WithLabelValues("signed_observation_request").Inc()
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- }()
|
|
|
- }
|
|
|
- case *gossipv1.GossipMessage_SignedObservation:
|
|
|
- if params.obsvC != nil {
|
|
|
- if err := common.PostMsgWithTimestamp[gossipv1.SignedObservation](m.SignedObservation, params.obsvC); err == nil {
|
|
|
- p2pMessagesReceived.WithLabelValues("observation").Inc()
|
|
|
- } else {
|
|
|
- if params.components.WarnChannelOverflow {
|
|
|
- logger.Warn("Ignoring SignedObservation because obsvC full", zap.String("hash", hex.EncodeToString(m.SignedObservation.Hash)))
|
|
|
+ case *gossipv1.GossipMessage_SignedChainGovernorConfig:
|
|
|
+ if params.signedGovCfgRecvC != nil {
|
|
|
+ params.signedGovCfgRecvC <- m.SignedChainGovernorConfig
|
|
|
+ }
|
|
|
+ case *gossipv1.GossipMessage_SignedChainGovernorStatus:
|
|
|
+ if params.signedGovStatusRecvC != nil {
|
|
|
+ params.signedGovStatusRecvC <- m.SignedChainGovernorStatus
|
|
|
}
|
|
|
- p2pReceiveChannelOverflow.WithLabelValues("observation").Inc()
|
|
|
+ default:
|
|
|
+ p2pMessagesReceived.WithLabelValues("unknown").Inc()
|
|
|
+ logger.Warn("received unknown message type on control topic (running outdated software?)",
|
|
|
+ zap.Any("payload", msg.Message),
|
|
|
+ zap.Binary("raw", envelope.Data),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
}
|
|
|
}
|
|
|
- case *gossipv1.GossipMessage_SignedVaaWithQuorum:
|
|
|
- if params.signedInC != nil {
|
|
|
- select {
|
|
|
- case params.signedInC <- m.SignedVaaWithQuorum:
|
|
|
- p2pMessagesReceived.WithLabelValues("signed_vaa_with_quorum").Inc()
|
|
|
- default:
|
|
|
- if params.components.WarnChannelOverflow {
|
|
|
- // TODO do not log this in production
|
|
|
- var hexStr string
|
|
|
- if vaa, err := vaa.Unmarshal(m.SignedVaaWithQuorum.Vaa); err == nil {
|
|
|
- hexStr = vaa.HexDigest()
|
|
|
+ }()
|
|
|
+ }
|
|
|
+
|
|
|
+ // This routine processes attestation messages received from gossip. //////////////////////////////////////////////
|
|
|
+ if attestationSubscription != nil {
|
|
|
+ go func() {
|
|
|
+ for {
|
|
|
+ envelope, err := attestationSubscription.Next(ctx) // Note: sub.Next(ctx) will return an error once ctx is canceled
|
|
|
+ if err != nil {
|
|
|
+ errC <- fmt.Errorf("failed to receive pubsub message on attestation topic: %w", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ var msg gossipv1.GossipMessage
|
|
|
+ err = proto.Unmarshal(envelope.Data, &msg)
|
|
|
+ if err != nil {
|
|
|
+ logger.Info("received invalid message on attestation topic",
|
|
|
+ zap.Binary("data", envelope.Data),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
+ p2pMessagesReceived.WithLabelValues("invalid").Inc()
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ if envelope.GetFrom() == h.ID() {
|
|
|
+ if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
+ logger.Debug("received message from ourselves on attestation topic, ignoring", zap.Any("payload", msg.Message))
|
|
|
+ }
|
|
|
+ p2pMessagesReceived.WithLabelValues("loopback").Inc()
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
+ logger.Debug("received message on attestation topic",
|
|
|
+ zap.Any("payload", msg.Message),
|
|
|
+ zap.Binary("raw", envelope.Data),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
+ }
|
|
|
+
|
|
|
+ switch m := msg.Message.(type) {
|
|
|
+ case *gossipv1.GossipMessage_SignedObservation:
|
|
|
+ if params.obsvRecvC != nil {
|
|
|
+ if err := common.PostMsgWithTimestamp(m.SignedObservation, params.obsvRecvC); err == nil {
|
|
|
+ p2pMessagesReceived.WithLabelValues("observation").Inc()
|
|
|
+ } else {
|
|
|
+ if params.components.WarnChannelOverflow {
|
|
|
+ logger.Warn("Ignoring SignedObservation because obsvRecvC is full", zap.String("addr", hex.EncodeToString(m.SignedObservation.Addr)))
|
|
|
+ }
|
|
|
+ p2pReceiveChannelOverflow.WithLabelValues("observation").Inc()
|
|
|
}
|
|
|
- logger.Warn("Ignoring SignedVaaWithQuorum because signedInC full", zap.String("hash", hexStr))
|
|
|
}
|
|
|
- p2pReceiveChannelOverflow.WithLabelValues("signed_vaa_with_quorum").Inc()
|
|
|
+ default:
|
|
|
+ p2pMessagesReceived.WithLabelValues("unknown").Inc()
|
|
|
+ logger.Warn("received unknown message type on attestation topic (running outdated software?)",
|
|
|
+ zap.Any("payload", msg.Message),
|
|
|
+ zap.Binary("raw", envelope.Data),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
}
|
|
|
}
|
|
|
- case *gossipv1.GossipMessage_SignedObservationRequest:
|
|
|
- if params.obsvReqC != nil {
|
|
|
- s := m.SignedObservationRequest
|
|
|
- gs := params.gst.Get()
|
|
|
- if gs == nil {
|
|
|
- if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
- logger.Debug("dropping SignedObservationRequest - no guardian set", zap.Any("value", s), zap.String("from", envelope.GetFrom().String()))
|
|
|
- }
|
|
|
- break
|
|
|
+ }()
|
|
|
+ }
|
|
|
+
|
|
|
+ // This routine processes signed VAA messages received from gossip. //////////////////////////////////////////////
|
|
|
+ if vaaSubscription != nil {
|
|
|
+ go func() {
|
|
|
+ for {
|
|
|
+ envelope, err := vaaSubscription.Next(ctx) // Note: sub.Next(ctx) will return an error once ctx is canceled
|
|
|
+ if err != nil {
|
|
|
+ errC <- fmt.Errorf("failed to receive pubsub message on vaa topic: %w", err)
|
|
|
+ return
|
|
|
}
|
|
|
- r, err := processSignedObservationRequest(s, gs)
|
|
|
+
|
|
|
+ var msg gossipv1.GossipMessage
|
|
|
+ err = proto.Unmarshal(envelope.Data, &msg)
|
|
|
if err != nil {
|
|
|
- p2pMessagesReceived.WithLabelValues("invalid_signed_observation_request").Inc()
|
|
|
+ logger.Info("received invalid message on vaa topic",
|
|
|
+ zap.Binary("data", envelope.Data),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
+ p2pMessagesReceived.WithLabelValues("invalid").Inc()
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ if envelope.GetFrom() == h.ID() {
|
|
|
if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
- logger.Debug("invalid signed observation request received",
|
|
|
+ logger.Debug("received message from ourselves on vaa topic, ignoring", zap.Any("payload", msg.Message))
|
|
|
+ }
|
|
|
+ p2pMessagesReceived.WithLabelValues("loopback").Inc()
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
+ logger.Debug("received message on vaa topic",
|
|
|
+ zap.Any("payload", msg.Message),
|
|
|
+ zap.Binary("raw", envelope.Data),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
+ }
|
|
|
+
|
|
|
+ switch m := msg.Message.(type) {
|
|
|
+ case *gossipv1.GossipMessage_SignedHeartbeat: // TODO: Get rid of this after the cutover.
|
|
|
+ s := m.SignedHeartbeat
|
|
|
+ gs := params.gst.Get()
|
|
|
+ if gs == nil {
|
|
|
+ // No valid guardian set yet - dropping heartbeat
|
|
|
+ logger.Log(params.components.SignedHeartbeatLogLevel, "skipping heartbeat - no guardian set",
|
|
|
+ zap.Any("value", s),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
+ break
|
|
|
+ }
|
|
|
+ if heartbeat, err := processSignedHeartbeat(envelope.GetFrom(), s, gs, params.gst, params.disableHeartbeatVerify); err != nil {
|
|
|
+ p2pMessagesReceived.WithLabelValues("invalid_heartbeat").Inc()
|
|
|
+ logger.Log(params.components.SignedHeartbeatLogLevel, "invalid signed heartbeat received",
|
|
|
zap.Error(err),
|
|
|
zap.Any("payload", msg.Message),
|
|
|
zap.Any("value", s),
|
|
|
zap.Binary("raw", envelope.Data),
|
|
|
zap.String("from", envelope.GetFrom().String()))
|
|
|
+ } else {
|
|
|
+ p2pMessagesReceived.WithLabelValues("valid_heartbeat").Inc()
|
|
|
+ logger.Log(params.components.SignedHeartbeatLogLevel, "valid signed heartbeat received",
|
|
|
+ zap.Any("value", heartbeat),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
+
|
|
|
+ func() {
|
|
|
+ if len(heartbeat.P2PNodeId) != 0 {
|
|
|
+ params.components.ProtectedHostByGuardianKeyLock.Lock()
|
|
|
+ defer params.components.ProtectedHostByGuardianKeyLock.Unlock()
|
|
|
+ var peerId peer.ID
|
|
|
+ if err = peerId.Unmarshal(heartbeat.P2PNodeId); err != nil {
|
|
|
+ logger.Error("p2p_node_id_in_heartbeat_invalid",
|
|
|
+ zap.Any("payload", msg.Message),
|
|
|
+ zap.Any("value", s),
|
|
|
+ zap.Binary("raw", envelope.Data),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
+ } else {
|
|
|
+ guardianAddr := eth_common.BytesToAddress(s.GuardianAddr)
|
|
|
+ if params.gk == nil || guardianAddr != ethcrypto.PubkeyToAddress(params.gk.PublicKey) {
|
|
|
+ prevPeerId, ok := params.components.ProtectedHostByGuardianKey[guardianAddr]
|
|
|
+ if ok {
|
|
|
+ if prevPeerId != peerId {
|
|
|
+ logger.Info("p2p_guardian_peer_changed",
|
|
|
+ zap.String("guardian_addr", guardianAddr.String()),
|
|
|
+ zap.String("prevPeerId", prevPeerId.String()),
|
|
|
+ zap.String("newPeerId", peerId.String()),
|
|
|
+ )
|
|
|
+ params.components.ConnMgr.Unprotect(prevPeerId, "heartbeat")
|
|
|
+ params.components.ConnMgr.Protect(peerId, "heartbeat")
|
|
|
+ params.components.ProtectedHostByGuardianKey[guardianAddr] = peerId
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ params.components.ConnMgr.Protect(peerId, "heartbeat")
|
|
|
+ params.components.ProtectedHostByGuardianKey[guardianAddr] = peerId
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
+ logger.Debug("p2p_node_id_not_in_heartbeat", zap.Error(err), zap.Any("payload", heartbeat.NodeName))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }()
|
|
|
}
|
|
|
- } else {
|
|
|
- if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
- logger.Debug("valid signed observation request received", zap.Any("value", r), zap.String("from", envelope.GetFrom().String()))
|
|
|
+ case *gossipv1.GossipMessage_SignedObservation: // TODO: Get rid of this after the cutover.
|
|
|
+ if params.obsvRecvC != nil {
|
|
|
+ if err := common.PostMsgWithTimestamp(m.SignedObservation, params.obsvRecvC); err == nil {
|
|
|
+ p2pMessagesReceived.WithLabelValues("observation").Inc()
|
|
|
+ } else {
|
|
|
+ if params.components.WarnChannelOverflow {
|
|
|
+ logger.Warn("Ignoring SignedObservation because obsvRecvC is full", zap.String("hash", hex.EncodeToString(m.SignedObservation.Hash)))
|
|
|
+ }
|
|
|
+ p2pReceiveChannelOverflow.WithLabelValues("observation").Inc()
|
|
|
+ }
|
|
|
}
|
|
|
+ case *gossipv1.GossipMessage_SignedVaaWithQuorum:
|
|
|
+ if params.signedIncomingVaaRecvC != nil {
|
|
|
+ select {
|
|
|
+ case params.signedIncomingVaaRecvC <- m.SignedVaaWithQuorum:
|
|
|
+ p2pMessagesReceived.WithLabelValues("signed_vaa_with_quorum").Inc()
|
|
|
+ default:
|
|
|
+ if params.components.WarnChannelOverflow {
|
|
|
+ var hexStr string
|
|
|
+ if vaa, err := vaa.Unmarshal(m.SignedVaaWithQuorum.Vaa); err == nil {
|
|
|
+ hexStr = vaa.HexDigest()
|
|
|
+ }
|
|
|
+ logger.Warn("Ignoring SignedVaaWithQuorum because signedIncomingVaaRecvC full", zap.String("hash", hexStr))
|
|
|
+ }
|
|
|
+ p2pReceiveChannelOverflow.WithLabelValues("signed_vaa_with_quorum").Inc()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case *gossipv1.GossipMessage_SignedObservationRequest: // TODO: Get rid of this after the cutover.
|
|
|
+ if params.obsvReqRecvC != nil {
|
|
|
+ s := m.SignedObservationRequest
|
|
|
+ gs := params.gst.Get()
|
|
|
+ if gs == nil {
|
|
|
+ if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
+ logger.Debug("dropping SignedObservationRequest - no guardian set", zap.Any("value", s), zap.String("from", envelope.GetFrom().String()))
|
|
|
+ }
|
|
|
+ break
|
|
|
+ }
|
|
|
+ r, err := processSignedObservationRequest(s, gs)
|
|
|
+ if err != nil {
|
|
|
+ p2pMessagesReceived.WithLabelValues("invalid_signed_observation_request").Inc()
|
|
|
+ if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
+ logger.Debug("invalid signed observation request received",
|
|
|
+ zap.Error(err),
|
|
|
+ zap.Any("payload", msg.Message),
|
|
|
+ zap.Any("value", s),
|
|
|
+ zap.Binary("raw", envelope.Data),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if logger.Level().Enabled(zapcore.DebugLevel) {
|
|
|
+ logger.Debug("valid signed observation request received", zap.Any("value", r), zap.String("from", envelope.GetFrom().String()))
|
|
|
+ }
|
|
|
|
|
|
- select {
|
|
|
- case params.obsvReqC <- r:
|
|
|
- p2pMessagesReceived.WithLabelValues("signed_observation_request").Inc()
|
|
|
- default:
|
|
|
- p2pReceiveChannelOverflow.WithLabelValues("signed_observation_request").Inc()
|
|
|
+ select {
|
|
|
+ case params.obsvReqRecvC <- r:
|
|
|
+ p2pMessagesReceived.WithLabelValues("signed_observation_request").Inc()
|
|
|
+ default:
|
|
|
+ p2pReceiveChannelOverflow.WithLabelValues("signed_observation_request").Inc()
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+ case *gossipv1.GossipMessage_SignedChainGovernorConfig: // TODO: Get rid of this after the cutover.
|
|
|
+ if params.signedGovCfgRecvC != nil {
|
|
|
+ params.signedGovCfgRecvC <- m.SignedChainGovernorConfig
|
|
|
+ }
|
|
|
+ case *gossipv1.GossipMessage_SignedChainGovernorStatus: // TODO: Get rid of this after the cutover.
|
|
|
+ if params.signedGovStatusRecvC != nil {
|
|
|
+ params.signedGovStatusRecvC <- m.SignedChainGovernorStatus
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ p2pMessagesReceived.WithLabelValues("unknown").Inc()
|
|
|
+ logger.Warn("received unknown message type on vaa topic (running outdated software?)",
|
|
|
+ zap.Any("payload", msg.Message),
|
|
|
+ zap.Binary("raw", envelope.Data),
|
|
|
+ zap.String("from", envelope.GetFrom().String()))
|
|
|
}
|
|
|
}
|
|
|
- case *gossipv1.GossipMessage_SignedChainGovernorConfig:
|
|
|
- if params.signedGovCfg != nil {
|
|
|
- params.signedGovCfg <- m.SignedChainGovernorConfig
|
|
|
- }
|
|
|
- case *gossipv1.GossipMessage_SignedChainGovernorStatus:
|
|
|
- if params.signedGovSt != nil {
|
|
|
- params.signedGovSt <- m.SignedChainGovernorStatus
|
|
|
- }
|
|
|
- default:
|
|
|
- p2pMessagesReceived.WithLabelValues("unknown").Inc()
|
|
|
- logger.Warn("received unknown message type (running outdated software?)",
|
|
|
- zap.Any("payload", msg.Message),
|
|
|
- zap.Binary("raw", envelope.Data),
|
|
|
- zap.String("from", envelope.GetFrom().String()))
|
|
|
- }
|
|
|
+ }()
|
|
|
+ }
|
|
|
+
|
|
|
+ // Wait for either a shutdown or a fatal error from a pubsub subscription.
|
|
|
+ select {
|
|
|
+ case <-ctx.Done():
|
|
|
+ return nil
|
|
|
+ case err := <-errC:
|
|
|
+ return err
|
|
|
}
|
|
|
}
|
|
|
}
|