mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-10-31 22:37:26 +00:00 
			
		
		
		
	resolve peer info issue, reorganize so this is a bit more sane
This commit is contained in:
		
							parent
							
								
									ebd7f723c6
								
							
						
					
					
						commit
						ea120d9c31
					
				| @ -1,123 +1,17 @@ | |||||||
| package ceremony | package ceremony | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" |  | ||||||
| 	"encoding/binary" |  | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" |  | ||||||
| 
 |  | ||||||
| 	"source.quilibrium.com/quilibrium/monorepo/node/config" |  | ||||||
| 
 | 
 | ||||||
| 	"github.com/iden3/go-iden3-crypto/poseidon" | 	"github.com/iden3/go-iden3-crypto/poseidon" | ||||||
| 	pcrypto "github.com/libp2p/go-libp2p/core/crypto" |  | ||||||
| 	"github.com/libp2p/go-libp2p/core/peer" |  | ||||||
| 	"github.com/pkg/errors" | 	"github.com/pkg/errors" | ||||||
| 	"go.uber.org/zap" | 	"go.uber.org/zap" | ||||||
| 	"google.golang.org/protobuf/proto" | 	"google.golang.org/protobuf/proto" | ||||||
| 	"google.golang.org/protobuf/types/known/anypb" | 	"google.golang.org/protobuf/types/known/anypb" | ||||||
| 	"source.quilibrium.com/quilibrium/monorepo/go-libp2p-blossomsub/pb" | 	"source.quilibrium.com/quilibrium/monorepo/go-libp2p-blossomsub/pb" | ||||||
| 	"source.quilibrium.com/quilibrium/monorepo/node/keys" |  | ||||||
| 	"source.quilibrium.com/quilibrium/monorepo/node/protobufs" | 	"source.quilibrium.com/quilibrium/monorepo/node/protobufs" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func (e *CeremonyDataClockConsensusEngine) runMessageHandler() { |  | ||||||
| 	for { |  | ||||||
| 		select { |  | ||||||
| 		case message := <-e.messageProcessorCh: |  | ||||||
| 			msg := &protobufs.Message{} |  | ||||||
| 
 |  | ||||||
| 			if err := proto.Unmarshal(message.Data, msg); err != nil { |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			e.peerMapMx.RLock() |  | ||||||
| 			peer, ok := e.peerMap[string(message.From)] |  | ||||||
| 			e.peerMapMx.RUnlock() |  | ||||||
| 
 |  | ||||||
| 			if ok && bytes.Compare(peer.version, config.GetMinimumVersion()) >= 0 { |  | ||||||
| 				for name := range e.executionEngines { |  | ||||||
| 					name := name |  | ||||||
| 					go func() error { |  | ||||||
| 						messages, err := e.executionEngines[name].ProcessMessage( |  | ||||||
| 							msg.Address, |  | ||||||
| 							msg, |  | ||||||
| 						) |  | ||||||
| 						if err != nil { |  | ||||||
| 							e.logger.Debug( |  | ||||||
| 								"could not process message for engine", |  | ||||||
| 								zap.Error(err), |  | ||||||
| 								zap.String("engine_name", name), |  | ||||||
| 							) |  | ||||||
| 							return nil |  | ||||||
| 						} |  | ||||||
| 
 |  | ||||||
| 						for _, appMessage := range messages { |  | ||||||
| 							appMsg := &anypb.Any{} |  | ||||||
| 							err := proto.Unmarshal(appMessage.Payload, appMsg) |  | ||||||
| 							if err != nil { |  | ||||||
| 								e.logger.Error( |  | ||||||
| 									"could not unmarshal app message", |  | ||||||
| 									zap.Error(err), |  | ||||||
| 									zap.String("engine_name", name), |  | ||||||
| 								) |  | ||||||
| 								continue |  | ||||||
| 							} |  | ||||||
| 
 |  | ||||||
| 							switch appMsg.TypeUrl { |  | ||||||
| 							case protobufs.CeremonyLobbyStateTransitionType: |  | ||||||
| 								t := &protobufs.CeremonyLobbyStateTransition{} |  | ||||||
| 								err := proto.Unmarshal(appMsg.Value, t) |  | ||||||
| 								if err != nil { |  | ||||||
| 									continue |  | ||||||
| 								} |  | ||||||
| 
 |  | ||||||
| 								if err := e.handleCeremonyLobbyStateTransition(t); err != nil { |  | ||||||
| 									continue |  | ||||||
| 								} |  | ||||||
| 							} |  | ||||||
| 						} |  | ||||||
| 
 |  | ||||||
| 						return nil |  | ||||||
| 					}() |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			any := &anypb.Any{} |  | ||||||
| 			if err := proto.Unmarshal(msg.Payload, any); err != nil { |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			go func() { |  | ||||||
| 				switch any.TypeUrl { |  | ||||||
| 				case protobufs.ClockFrameType: |  | ||||||
| 					if !ok || bytes.Compare( |  | ||||||
| 						peer.version, |  | ||||||
| 						config.GetMinimumVersion(), |  | ||||||
| 					) < 0 { |  | ||||||
| 						return |  | ||||||
| 					} |  | ||||||
| 					if err := e.handleClockFrameData( |  | ||||||
| 						message.From, |  | ||||||
| 						msg.Address, |  | ||||||
| 						any, |  | ||||||
| 						false, |  | ||||||
| 					); err != nil { |  | ||||||
| 						return |  | ||||||
| 					} |  | ||||||
| 				case protobufs.CeremonyPeerListAnnounceType: |  | ||||||
| 					if err := e.handleCeremonyPeerListAnnounce( |  | ||||||
| 						message.From, |  | ||||||
| 						msg.Address, |  | ||||||
| 						any, |  | ||||||
| 					); err != nil { |  | ||||||
| 						return |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			}() |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (e *CeremonyDataClockConsensusEngine) handleMessage( | func (e *CeremonyDataClockConsensusEngine) handleMessage( | ||||||
| 	message *pb.Message, | 	message *pb.Message, | ||||||
| ) error { | ) error { | ||||||
| @ -135,223 +29,6 @@ func (e *CeremonyDataClockConsensusEngine) handleMessage( | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (e *CeremonyDataClockConsensusEngine) handleCeremonyPeerListAnnounce( |  | ||||||
| 	peerID []byte, |  | ||||||
| 	address []byte, |  | ||||||
| 	any *anypb.Any, |  | ||||||
| ) error { |  | ||||||
| 	announce := &protobufs.CeremonyPeerListAnnounce{} |  | ||||||
| 	if err := any.UnmarshalTo(announce); err != nil { |  | ||||||
| 		return errors.Wrap(err, "handle ceremony peer list announce") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	for _, p := range announce.PeerList { |  | ||||||
| 		if bytes.Equal(p.PeerId, e.pubSub.GetPeerID()) { |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if !bytes.Equal(p.PeerId, peerID) { |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if p.PublicKey == nil || p.Signature == nil || p.Version == nil { |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if p.PublicKey != nil && p.Signature != nil && p.Version != nil { |  | ||||||
| 			key, err := pcrypto.UnmarshalEd448PublicKey(p.PublicKey) |  | ||||||
| 			if err != nil { |  | ||||||
| 				e.logger.Warn( |  | ||||||
| 					"peer announcement contained invalid pubkey", |  | ||||||
| 					zap.Binary("public_key", p.PublicKey), |  | ||||||
| 				) |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if !(peer.ID(p.PeerId)).MatchesPublicKey(key) { |  | ||||||
| 				e.logger.Warn( |  | ||||||
| 					"peer announcement peer id does not match pubkey", |  | ||||||
| 					zap.Binary("peer_id", p.PeerId), |  | ||||||
| 					zap.Binary("public_key", p.PublicKey), |  | ||||||
| 				) |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			msg := binary.BigEndian.AppendUint64([]byte{}, p.MaxFrame) |  | ||||||
| 			msg = append(msg, p.Version...) |  | ||||||
| 			msg = binary.BigEndian.AppendUint64(msg, uint64(p.Timestamp)) |  | ||||||
| 			b, err := key.Verify(msg, p.Signature) |  | ||||||
| 			if err != nil || !b { |  | ||||||
| 				e.logger.Warn( |  | ||||||
| 					"peer provided invalid signature", |  | ||||||
| 					zap.Binary("msg", msg), |  | ||||||
| 					zap.Binary("public_key", p.PublicKey), |  | ||||||
| 					zap.Binary("signature", p.Signature), |  | ||||||
| 				) |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if bytes.Compare(p.Version, config.GetMinimumVersion()) < 0 && |  | ||||||
| 				p.Timestamp > config.GetMinimumVersionCutoff().UnixMilli() { |  | ||||||
| 				e.logger.Debug( |  | ||||||
| 					"peer provided outdated version, penalizing app score", |  | ||||||
| 					zap.Binary("peer_id", p.PeerId), |  | ||||||
| 				) |  | ||||||
| 				e.pubSub.SetPeerScore(p.PeerId, -10000) |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		e.peerMapMx.RLock() |  | ||||||
| 		if _, ok := e.uncooperativePeersMap[string(p.PeerId)]; ok { |  | ||||||
| 			e.peerMapMx.RUnlock() |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 		e.peerMapMx.RUnlock() |  | ||||||
| 
 |  | ||||||
| 		multiaddr := e.pubSub.GetMultiaddrOfPeer(p.PeerId) |  | ||||||
| 
 |  | ||||||
| 		e.pubSub.SetPeerScore(p.PeerId, 10) |  | ||||||
| 
 |  | ||||||
| 		e.peerMapMx.RLock() |  | ||||||
| 		existing, ok := e.peerMap[string(p.PeerId)] |  | ||||||
| 		e.peerMapMx.RUnlock() |  | ||||||
| 
 |  | ||||||
| 		if ok { |  | ||||||
| 			if existing.signature != nil && p.Signature == nil { |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if existing.publicKey != nil && p.PublicKey == nil { |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if existing.version != nil && p.Version == nil { |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if existing.timestamp > p.Timestamp { |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		e.peerMapMx.Lock() |  | ||||||
| 		e.peerMap[string(p.PeerId)] = &peerInfo{ |  | ||||||
| 			peerId:        p.PeerId, |  | ||||||
| 			multiaddr:     multiaddr, |  | ||||||
| 			maxFrame:      p.MaxFrame, |  | ||||||
| 			direct:        bytes.Equal(p.PeerId, peerID), |  | ||||||
| 			lastSeen:      time.Now().Unix(), |  | ||||||
| 			timestamp:     p.Timestamp, |  | ||||||
| 			version:       p.Version, |  | ||||||
| 			signature:     p.Signature, |  | ||||||
| 			publicKey:     p.PublicKey, |  | ||||||
| 			totalDistance: p.TotalDistance, |  | ||||||
| 		} |  | ||||||
| 		e.peerMapMx.Unlock() |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (e *CeremonyDataClockConsensusEngine) handleCeremonyLobbyStateTransition( |  | ||||||
| 	transition *protobufs.CeremonyLobbyStateTransition, |  | ||||||
| ) error { |  | ||||||
| 	if len(transition.TransitionInputs) != len(transition.TypeUrls) { |  | ||||||
| 		return errors.Wrap( |  | ||||||
| 			errors.New("invalid state transition"), |  | ||||||
| 			"handle ceremony lobby state transition", |  | ||||||
| 		) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	e.stagedLobbyStateTransitionsMx.Lock() |  | ||||||
| 	if e.stagedLobbyStateTransitions == nil { |  | ||||||
| 		e.stagedLobbyStateTransitions = &protobufs.CeremonyLobbyStateTransition{} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	found := false |  | ||||||
| 	for _, ti := range e.stagedLobbyStateTransitions.TransitionInputs { |  | ||||||
| 		for _, nti := range transition.TransitionInputs { |  | ||||||
| 			if bytes.Equal(ti, nti) { |  | ||||||
| 				found = true |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if !found { |  | ||||||
| 		for i := range transition.TransitionInputs { |  | ||||||
| 			e.stagedLobbyStateTransitions.TypeUrls = append( |  | ||||||
| 				e.stagedLobbyStateTransitions.TypeUrls, |  | ||||||
| 				transition.TypeUrls[i], |  | ||||||
| 			) |  | ||||||
| 			e.stagedLobbyStateTransitions.TransitionInputs = append( |  | ||||||
| 				e.stagedLobbyStateTransitions.TransitionInputs, |  | ||||||
| 				transition.TransitionInputs[i], |  | ||||||
| 			) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	e.stagedLobbyStateTransitionsMx.Unlock() |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (e *CeremonyDataClockConsensusEngine) handleClockFrameData( |  | ||||||
| 	peerID []byte, |  | ||||||
| 	address []byte, |  | ||||||
| 	any *anypb.Any, |  | ||||||
| 	isSync bool, |  | ||||||
| ) error { |  | ||||||
| 	frame := &protobufs.ClockFrame{} |  | ||||||
| 	if err := any.UnmarshalTo(frame); err != nil { |  | ||||||
| 		return errors.Wrap(err, "handle clock frame data") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	addr, err := poseidon.HashBytes( |  | ||||||
| 		frame.GetPublicKeySignatureEd448().PublicKey.KeyValue, |  | ||||||
| 	) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return errors.Wrap(err, "handle clock frame data") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	prover := e.frameProverTrie.FindNearest(addr.Bytes()) |  | ||||||
| 	if !bytes.Equal(prover.External.Key, addr.Bytes()) { |  | ||||||
| 		e.logger.Info( |  | ||||||
| 			"prover not in trie at frame, address may be in fork", |  | ||||||
| 			zap.Binary("address", address), |  | ||||||
| 			zap.Binary("filter", frame.Filter), |  | ||||||
| 			zap.Uint64("frame_number", frame.FrameNumber), |  | ||||||
| 		) |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	e.logger.Info( |  | ||||||
| 		"got clock frame", |  | ||||||
| 		zap.Binary("address", address), |  | ||||||
| 		zap.Binary("filter", frame.Filter), |  | ||||||
| 		zap.Uint64("frame_number", frame.FrameNumber), |  | ||||||
| 		zap.Int("proof_count", len(frame.AggregateProofs)), |  | ||||||
| 	) |  | ||||||
| 
 |  | ||||||
| 	if err := e.frameProver.VerifyDataClockFrame(frame); err != nil { |  | ||||||
| 		e.logger.Error("could not verify clock frame", zap.Error(err)) |  | ||||||
| 		return errors.Wrap(err, "handle clock frame data") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err := e.inclusionProver.VerifyFrame(frame); err != nil { |  | ||||||
| 		e.logger.Error("could not verify clock frame", zap.Error(err)) |  | ||||||
| 		return errors.Wrap(err, "handle clock frame data") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	e.logger.Info( |  | ||||||
| 		"clock frame was valid", |  | ||||||
| 		zap.Binary("address", address), |  | ||||||
| 		zap.Binary("filter", frame.Filter), |  | ||||||
| 		zap.Uint64("frame_number", frame.FrameNumber), |  | ||||||
| 	) |  | ||||||
| 
 |  | ||||||
| 	e.dataTimeReel.Insert(frame) |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (e *CeremonyDataClockConsensusEngine) publishProof( | func (e *CeremonyDataClockConsensusEngine) publishProof( | ||||||
| 	frame *protobufs.ClockFrame, | 	frame *protobufs.ClockFrame, | ||||||
| ) error { | ) error { | ||||||
| @ -414,37 +91,3 @@ func (e *CeremonyDataClockConsensusEngine) publishMessage( | |||||||
| 	} | 	} | ||||||
| 	return e.pubSub.PublishToBitmask(filter, data) | 	return e.pubSub.PublishToBitmask(filter, data) | ||||||
| } | } | ||||||
| 
 |  | ||||||
| func (e *CeremonyDataClockConsensusEngine) createCommunicationKeys() error { |  | ||||||
| 	_, err := e.keyManager.GetAgreementKey("q-ratchet-idk") |  | ||||||
| 	if err != nil { |  | ||||||
| 		if errors.Is(err, keys.KeyNotFoundErr) { |  | ||||||
| 			_, err = e.keyManager.CreateAgreementKey( |  | ||||||
| 				"q-ratchet-idk", |  | ||||||
| 				keys.KeyTypeX448, |  | ||||||
| 			) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return errors.Wrap(err, "announce key bundle") |  | ||||||
| 			} |  | ||||||
| 		} else { |  | ||||||
| 			return errors.Wrap(err, "announce key bundle") |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	_, err = e.keyManager.GetAgreementKey("q-ratchet-spk") |  | ||||||
| 	if err != nil { |  | ||||||
| 		if errors.Is(err, keys.KeyNotFoundErr) { |  | ||||||
| 			_, err = e.keyManager.CreateAgreementKey( |  | ||||||
| 				"q-ratchet-spk", |  | ||||||
| 				keys.KeyTypeX448, |  | ||||||
| 			) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return errors.Wrap(err, "announce key bundle") |  | ||||||
| 			} |  | ||||||
| 		} else { |  | ||||||
| 			return errors.Wrap(err, "announce key bundle") |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -274,7 +274,7 @@ func (e *CeremonyDataClockConsensusEngine) Start() <-chan error { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	go func() { | 	go func() { | ||||||
| 		e.runLoop() | 		e.runMessageHandler() | ||||||
| 	}() | 	}() | ||||||
| 
 | 
 | ||||||
| 	e.logger.Info("subscribing to pubsub messages") | 	e.logger.Info("subscribing to pubsub messages") | ||||||
| @ -302,7 +302,7 @@ func (e *CeremonyDataClockConsensusEngine) Start() <-chan error { | |||||||
| 		thresholdBeforeConfirming := 4 | 		thresholdBeforeConfirming := 4 | ||||||
| 
 | 
 | ||||||
| 		for { | 		for { | ||||||
| 			time.Sleep(30 * time.Second) | 			time.Sleep(120 * time.Second) | ||||||
| 
 | 
 | ||||||
| 			list := &protobufs.CeremonyPeerListAnnounce{ | 			list := &protobufs.CeremonyPeerListAnnounce{ | ||||||
| 				PeerList: []*protobufs.CeremonyPeer{}, | 				PeerList: []*protobufs.CeremonyPeer{}, | ||||||
| @ -612,3 +612,37 @@ func ( | |||||||
| 	e.peerMapMx.RUnlock() | 	e.peerMapMx.RUnlock() | ||||||
| 	return resp | 	return resp | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func (e *CeremonyDataClockConsensusEngine) createCommunicationKeys() error { | ||||||
|  | 	_, err := e.keyManager.GetAgreementKey("q-ratchet-idk") | ||||||
|  | 	if err != nil { | ||||||
|  | 		if errors.Is(err, keys.KeyNotFoundErr) { | ||||||
|  | 			_, err = e.keyManager.CreateAgreementKey( | ||||||
|  | 				"q-ratchet-idk", | ||||||
|  | 				keys.KeyTypeX448, | ||||||
|  | 			) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return errors.Wrap(err, "announce key bundle") | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			return errors.Wrap(err, "announce key bundle") | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	_, err = e.keyManager.GetAgreementKey("q-ratchet-spk") | ||||||
|  | 	if err != nil { | ||||||
|  | 		if errors.Is(err, keys.KeyNotFoundErr) { | ||||||
|  | 			_, err = e.keyManager.CreateAgreementKey( | ||||||
|  | 				"q-ratchet-spk", | ||||||
|  | 				keys.KeyTypeX448, | ||||||
|  | 			) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return errors.Wrap(err, "announce key bundle") | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			return errors.Wrap(err, "announce key bundle") | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										332
									
								
								node/consensus/ceremony/message_handler.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										332
									
								
								node/consensus/ceremony/message_handler.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,332 @@ | |||||||
|  | package ceremony | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"encoding/binary" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"github.com/iden3/go-iden3-crypto/poseidon" | ||||||
|  | 	pcrypto "github.com/libp2p/go-libp2p/core/crypto" | ||||||
|  | 	"github.com/libp2p/go-libp2p/core/peer" | ||||||
|  | 	"github.com/pkg/errors" | ||||||
|  | 	"go.uber.org/zap" | ||||||
|  | 	"google.golang.org/protobuf/proto" | ||||||
|  | 	"google.golang.org/protobuf/types/known/anypb" | ||||||
|  | 	"source.quilibrium.com/quilibrium/monorepo/node/config" | ||||||
|  | 	"source.quilibrium.com/quilibrium/monorepo/node/protobufs" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func (e *CeremonyDataClockConsensusEngine) runMessageHandler() { | ||||||
|  | 	for { | ||||||
|  | 		select { | ||||||
|  | 		case message := <-e.messageProcessorCh: | ||||||
|  | 			msg := &protobufs.Message{} | ||||||
|  | 
 | ||||||
|  | 			if err := proto.Unmarshal(message.Data, msg); err != nil { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			e.peerMapMx.RLock() | ||||||
|  | 			peer, ok := e.peerMap[string(message.From)] | ||||||
|  | 			e.peerMapMx.RUnlock() | ||||||
|  | 
 | ||||||
|  | 			if ok && bytes.Compare(peer.version, config.GetMinimumVersion()) >= 0 { | ||||||
|  | 				for name := range e.executionEngines { | ||||||
|  | 					name := name | ||||||
|  | 					go func() error { | ||||||
|  | 						messages, err := e.executionEngines[name].ProcessMessage( | ||||||
|  | 							msg.Address, | ||||||
|  | 							msg, | ||||||
|  | 						) | ||||||
|  | 						if err != nil { | ||||||
|  | 							e.logger.Debug( | ||||||
|  | 								"could not process message for engine", | ||||||
|  | 								zap.Error(err), | ||||||
|  | 								zap.String("engine_name", name), | ||||||
|  | 							) | ||||||
|  | 							return nil | ||||||
|  | 						} | ||||||
|  | 
 | ||||||
|  | 						for _, appMessage := range messages { | ||||||
|  | 							appMsg := &anypb.Any{} | ||||||
|  | 							err := proto.Unmarshal(appMessage.Payload, appMsg) | ||||||
|  | 							if err != nil { | ||||||
|  | 								e.logger.Error( | ||||||
|  | 									"could not unmarshal app message", | ||||||
|  | 									zap.Error(err), | ||||||
|  | 									zap.String("engine_name", name), | ||||||
|  | 								) | ||||||
|  | 								continue | ||||||
|  | 							} | ||||||
|  | 
 | ||||||
|  | 							switch appMsg.TypeUrl { | ||||||
|  | 							case protobufs.CeremonyLobbyStateTransitionType: | ||||||
|  | 								t := &protobufs.CeremonyLobbyStateTransition{} | ||||||
|  | 								err := proto.Unmarshal(appMsg.Value, t) | ||||||
|  | 								if err != nil { | ||||||
|  | 									continue | ||||||
|  | 								} | ||||||
|  | 
 | ||||||
|  | 								if err := e.handleCeremonyLobbyStateTransition(t); err != nil { | ||||||
|  | 									continue | ||||||
|  | 								} | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 
 | ||||||
|  | 						return nil | ||||||
|  | 					}() | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			any := &anypb.Any{} | ||||||
|  | 			if err := proto.Unmarshal(msg.Payload, any); err != nil { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			go func() { | ||||||
|  | 				switch any.TypeUrl { | ||||||
|  | 				case protobufs.ClockFrameType: | ||||||
|  | 					if !ok || bytes.Compare( | ||||||
|  | 						peer.version, | ||||||
|  | 						config.GetMinimumVersion(), | ||||||
|  | 					) < 0 { | ||||||
|  | 						return | ||||||
|  | 					} | ||||||
|  | 					if err := e.handleClockFrameData( | ||||||
|  | 						message.From, | ||||||
|  | 						msg.Address, | ||||||
|  | 						any, | ||||||
|  | 						false, | ||||||
|  | 					); err != nil { | ||||||
|  | 						return | ||||||
|  | 					} | ||||||
|  | 				case protobufs.CeremonyPeerListAnnounceType: | ||||||
|  | 					if err := e.handleCeremonyPeerListAnnounce( | ||||||
|  | 						message.From, | ||||||
|  | 						msg.Address, | ||||||
|  | 						any, | ||||||
|  | 					); err != nil { | ||||||
|  | 						return | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			}() | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (e *CeremonyDataClockConsensusEngine) handleCeremonyPeerListAnnounce( | ||||||
|  | 	peerID []byte, | ||||||
|  | 	address []byte, | ||||||
|  | 	any *anypb.Any, | ||||||
|  | ) error { | ||||||
|  | 	announce := &protobufs.CeremonyPeerListAnnounce{} | ||||||
|  | 	if err := any.UnmarshalTo(announce); err != nil { | ||||||
|  | 		return errors.Wrap(err, "handle ceremony peer list announce") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, p := range announce.PeerList { | ||||||
|  | 		if bytes.Equal(p.PeerId, e.pubSub.GetPeerID()) { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if !bytes.Equal(p.PeerId, peerID) { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if p.PublicKey == nil || p.Signature == nil || p.Version == nil { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if p.PublicKey != nil && p.Signature != nil && p.Version != nil { | ||||||
|  | 			key, err := pcrypto.UnmarshalEd448PublicKey(p.PublicKey) | ||||||
|  | 			if err != nil { | ||||||
|  | 				e.logger.Warn( | ||||||
|  | 					"peer announcement contained invalid pubkey", | ||||||
|  | 					zap.Binary("public_key", p.PublicKey), | ||||||
|  | 				) | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if !(peer.ID(p.PeerId)).MatchesPublicKey(key) { | ||||||
|  | 				e.logger.Warn( | ||||||
|  | 					"peer announcement peer id does not match pubkey", | ||||||
|  | 					zap.Binary("peer_id", p.PeerId), | ||||||
|  | 					zap.Binary("public_key", p.PublicKey), | ||||||
|  | 				) | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			msg := binary.BigEndian.AppendUint64([]byte{}, p.MaxFrame) | ||||||
|  | 			msg = append(msg, p.Version...) | ||||||
|  | 			msg = binary.BigEndian.AppendUint64(msg, uint64(p.Timestamp)) | ||||||
|  | 			b, err := key.Verify(msg, p.Signature) | ||||||
|  | 			if err != nil || !b { | ||||||
|  | 				e.logger.Warn( | ||||||
|  | 					"peer provided invalid signature", | ||||||
|  | 					zap.Binary("msg", msg), | ||||||
|  | 					zap.Binary("public_key", p.PublicKey), | ||||||
|  | 					zap.Binary("signature", p.Signature), | ||||||
|  | 				) | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if bytes.Compare(p.Version, config.GetMinimumVersion()) < 0 && | ||||||
|  | 				p.Timestamp > config.GetMinimumVersionCutoff().UnixMilli() { | ||||||
|  | 				e.logger.Debug( | ||||||
|  | 					"peer provided outdated version, penalizing app score", | ||||||
|  | 					zap.Binary("peer_id", p.PeerId), | ||||||
|  | 				) | ||||||
|  | 				e.pubSub.SetPeerScore(p.PeerId, -10000) | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		e.peerMapMx.RLock() | ||||||
|  | 		if _, ok := e.uncooperativePeersMap[string(p.PeerId)]; ok { | ||||||
|  | 			e.peerMapMx.RUnlock() | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		e.peerMapMx.RUnlock() | ||||||
|  | 
 | ||||||
|  | 		multiaddr := e.pubSub.GetMultiaddrOfPeer(p.PeerId) | ||||||
|  | 
 | ||||||
|  | 		e.pubSub.SetPeerScore(p.PeerId, 10) | ||||||
|  | 
 | ||||||
|  | 		e.peerMapMx.RLock() | ||||||
|  | 		existing, ok := e.peerMap[string(p.PeerId)] | ||||||
|  | 		e.peerMapMx.RUnlock() | ||||||
|  | 
 | ||||||
|  | 		if ok { | ||||||
|  | 			if existing.signature != nil && p.Signature == nil { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if existing.publicKey != nil && p.PublicKey == nil { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if existing.version != nil && p.Version == nil { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if existing.timestamp > p.Timestamp { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		e.peerMapMx.Lock() | ||||||
|  | 		e.peerMap[string(p.PeerId)] = &peerInfo{ | ||||||
|  | 			peerId:        p.PeerId, | ||||||
|  | 			multiaddr:     multiaddr, | ||||||
|  | 			maxFrame:      p.MaxFrame, | ||||||
|  | 			direct:        bytes.Equal(p.PeerId, peerID), | ||||||
|  | 			lastSeen:      time.Now().Unix(), | ||||||
|  | 			timestamp:     p.Timestamp, | ||||||
|  | 			version:       p.Version, | ||||||
|  | 			signature:     p.Signature, | ||||||
|  | 			publicKey:     p.PublicKey, | ||||||
|  | 			totalDistance: p.TotalDistance, | ||||||
|  | 		} | ||||||
|  | 		e.peerMapMx.Unlock() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (e *CeremonyDataClockConsensusEngine) handleCeremonyLobbyStateTransition( | ||||||
|  | 	transition *protobufs.CeremonyLobbyStateTransition, | ||||||
|  | ) error { | ||||||
|  | 	if len(transition.TransitionInputs) != len(transition.TypeUrls) { | ||||||
|  | 		return errors.Wrap( | ||||||
|  | 			errors.New("invalid state transition"), | ||||||
|  | 			"handle ceremony lobby state transition", | ||||||
|  | 		) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	e.stagedLobbyStateTransitionsMx.Lock() | ||||||
|  | 	if e.stagedLobbyStateTransitions == nil { | ||||||
|  | 		e.stagedLobbyStateTransitions = &protobufs.CeremonyLobbyStateTransition{} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	found := false | ||||||
|  | 	for _, ti := range e.stagedLobbyStateTransitions.TransitionInputs { | ||||||
|  | 		for _, nti := range transition.TransitionInputs { | ||||||
|  | 			if bytes.Equal(ti, nti) { | ||||||
|  | 				found = true | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if !found { | ||||||
|  | 		for i := range transition.TransitionInputs { | ||||||
|  | 			e.stagedLobbyStateTransitions.TypeUrls = append( | ||||||
|  | 				e.stagedLobbyStateTransitions.TypeUrls, | ||||||
|  | 				transition.TypeUrls[i], | ||||||
|  | 			) | ||||||
|  | 			e.stagedLobbyStateTransitions.TransitionInputs = append( | ||||||
|  | 				e.stagedLobbyStateTransitions.TransitionInputs, | ||||||
|  | 				transition.TransitionInputs[i], | ||||||
|  | 			) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	e.stagedLobbyStateTransitionsMx.Unlock() | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (e *CeremonyDataClockConsensusEngine) handleClockFrameData( | ||||||
|  | 	peerID []byte, | ||||||
|  | 	address []byte, | ||||||
|  | 	any *anypb.Any, | ||||||
|  | 	isSync bool, | ||||||
|  | ) error { | ||||||
|  | 	frame := &protobufs.ClockFrame{} | ||||||
|  | 	if err := any.UnmarshalTo(frame); err != nil { | ||||||
|  | 		return errors.Wrap(err, "handle clock frame data") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	addr, err := poseidon.HashBytes( | ||||||
|  | 		frame.GetPublicKeySignatureEd448().PublicKey.KeyValue, | ||||||
|  | 	) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return errors.Wrap(err, "handle clock frame data") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	prover := e.frameProverTrie.FindNearest(addr.Bytes()) | ||||||
|  | 	if !bytes.Equal(prover.External.Key, addr.Bytes()) { | ||||||
|  | 		e.logger.Info( | ||||||
|  | 			"prover not in trie at frame, address may be in fork", | ||||||
|  | 			zap.Binary("address", address), | ||||||
|  | 			zap.Binary("filter", frame.Filter), | ||||||
|  | 			zap.Uint64("frame_number", frame.FrameNumber), | ||||||
|  | 		) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	e.logger.Info( | ||||||
|  | 		"got clock frame", | ||||||
|  | 		zap.Binary("address", address), | ||||||
|  | 		zap.Binary("filter", frame.Filter), | ||||||
|  | 		zap.Uint64("frame_number", frame.FrameNumber), | ||||||
|  | 		zap.Int("proof_count", len(frame.AggregateProofs)), | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	if err := e.frameProver.VerifyDataClockFrame(frame); err != nil { | ||||||
|  | 		e.logger.Error("could not verify clock frame", zap.Error(err)) | ||||||
|  | 		return errors.Wrap(err, "handle clock frame data") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := e.inclusionProver.VerifyFrame(frame); err != nil { | ||||||
|  | 		e.logger.Error("could not verify clock frame", zap.Error(err)) | ||||||
|  | 		return errors.Wrap(err, "handle clock frame data") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	e.logger.Info( | ||||||
|  | 		"clock frame was valid", | ||||||
|  | 		zap.Binary("address", address), | ||||||
|  | 		zap.Binary("filter", frame.Filter), | ||||||
|  | 		zap.Uint64("frame_number", frame.FrameNumber), | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	e.dataTimeReel.Insert(frame) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Cassandra Heart
						Cassandra Heart