mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-11-04 14:57:27 +00:00 
			
		
		
		
	QOL – fix crash/shutdown reentry bug, make validation faster
This commit is contained in:
		
							parent
							
								
									d1486d5be7
								
							
						
					
					
						commit
						2525c4ce7e
					
				@ -4,6 +4,7 @@ import (
 | 
				
			|||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/pkg/errors"
 | 
						"github.com/pkg/errors"
 | 
				
			||||||
 | 
						"golang.org/x/sync/errgroup"
 | 
				
			||||||
	"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/core/curves"
 | 
						"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/core/curves"
 | 
				
			||||||
	"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
 | 
						"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -36,42 +37,59 @@ func (a *CeremonyApplication) applyTranscript(
 | 
				
			|||||||
		)
 | 
							)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	g1s := []*curves.PointBls48581G1{}
 | 
						g1s := make([]*curves.PointBls48581G1, len(a.UpdatedTranscript.G1Powers))
 | 
				
			||||||
 | 
						eg := errgroup.Group{}
 | 
				
			||||||
 | 
						eg.SetLimit(100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := range a.UpdatedTranscript.G1Powers {
 | 
						for i := range a.UpdatedTranscript.G1Powers {
 | 
				
			||||||
		if !bytes.Equal(
 | 
							i := i
 | 
				
			||||||
			a.UpdatedTranscript.G1Powers[i].KeyValue,
 | 
							eg.Go(func() error {
 | 
				
			||||||
			transcript.G1Powers[i].KeyValue,
 | 
								if !bytes.Equal(
 | 
				
			||||||
		) {
 | 
									a.UpdatedTranscript.G1Powers[i].KeyValue,
 | 
				
			||||||
			return errors.Wrap(errors.New("invalid g1s"), "apply transcript")
 | 
									transcript.G1Powers[i].KeyValue,
 | 
				
			||||||
		}
 | 
								) {
 | 
				
			||||||
 | 
									return errors.Wrap(errors.New("invalid g1s"), "apply transcript")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		g1 := &curves.PointBls48581G1{}
 | 
								g1 := &curves.PointBls48581G1{}
 | 
				
			||||||
		x, err := g1.FromAffineCompressed(a.UpdatedTranscript.G1Powers[i].KeyValue)
 | 
								x, err := g1.FromAffineCompressed(a.UpdatedTranscript.G1Powers[i].KeyValue)
 | 
				
			||||||
		if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
			return errors.Wrap(err, "apply transcript")
 | 
									return errors.Wrap(err, "apply transcript")
 | 
				
			||||||
		}
 | 
								}
 | 
				
			||||||
		g1, _ = x.(*curves.PointBls48581G1)
 | 
								g1, _ = x.(*curves.PointBls48581G1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		g1s = append(g1s, g1)
 | 
								g1s[i] = g1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	g2s := []*curves.PointBls48581G2{}
 | 
						g2s := make([]*curves.PointBls48581G2, len(a.UpdatedTranscript.G2Powers))
 | 
				
			||||||
	for i := range a.UpdatedTranscript.G2Powers {
 | 
						for i := range a.UpdatedTranscript.G2Powers {
 | 
				
			||||||
		if !bytes.Equal(
 | 
							i := i
 | 
				
			||||||
			a.UpdatedTranscript.G2Powers[i].KeyValue,
 | 
							eg.Go(func() error {
 | 
				
			||||||
			transcript.G2Powers[i].KeyValue,
 | 
								if !bytes.Equal(
 | 
				
			||||||
		) {
 | 
									a.UpdatedTranscript.G2Powers[i].KeyValue,
 | 
				
			||||||
			return errors.Wrap(errors.New("invalid g2s"), "apply transcript")
 | 
									transcript.G2Powers[i].KeyValue,
 | 
				
			||||||
		}
 | 
								) {
 | 
				
			||||||
 | 
									return errors.Wrap(errors.New("invalid g2s"), "apply transcript")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		g2 := &curves.PointBls48581G2{}
 | 
								g2 := &curves.PointBls48581G2{}
 | 
				
			||||||
		x, err := g2.FromAffineCompressed(a.UpdatedTranscript.G2Powers[i].KeyValue)
 | 
								x, err := g2.FromAffineCompressed(a.UpdatedTranscript.G2Powers[i].KeyValue)
 | 
				
			||||||
		if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
			return errors.Wrap(err, "apply transcript")
 | 
									return errors.Wrap(err, "apply transcript")
 | 
				
			||||||
		}
 | 
								}
 | 
				
			||||||
		g2, _ = x.(*curves.PointBls48581G2)
 | 
								g2, _ = x.(*curves.PointBls48581G2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		g2s = append(g2s, g2)
 | 
								g2s[i] = g2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := eg.Wait(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	g1Witnesses := []*curves.PointBls48581G1{}
 | 
						g1Witnesses := []*curves.PointBls48581G1{}
 | 
				
			||||||
 | 
				
			|||||||
@ -70,7 +70,7 @@ func ProcessRound(
 | 
				
			|||||||
			for !participants[j].IsDone() {
 | 
								for !participants[j].IsDone() {
 | 
				
			||||||
				var err error
 | 
									var err error
 | 
				
			||||||
				if isReceiver {
 | 
									if isReceiver {
 | 
				
			||||||
					msg, err = recv(seq, append(append([]byte{}, roundPeers[j]...), i...))
 | 
										msg, err = recv(seq, roundPeers[j])
 | 
				
			||||||
					if err != nil {
 | 
										if err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
@ -81,13 +81,13 @@ func ProcessRound(
 | 
				
			|||||||
					return err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				err = send(seq, append(append([]byte{}, i...), roundPeers[j]...), next)
 | 
									err = send(seq, roundPeers[j], next)
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					return err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if !isReceiver {
 | 
									if !isReceiver {
 | 
				
			||||||
					msg, err = recv(seq, append(append([]byte{}, roundPeers[j]...), i...))
 | 
										msg, err = recv(seq, roundPeers[j])
 | 
				
			||||||
					if err != nil {
 | 
										if err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
				
			|||||||
@ -196,36 +196,39 @@ func TestProcessRound(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		peerSecrets = append(peerSecrets, secrets)
 | 
							peerSecrets = append(peerSecrets, secrets)
 | 
				
			||||||
		originalPeerSecrets = append(originalPeerSecrets, originalSecrets)
 | 
							originalPeerSecrets = append(originalPeerSecrets, originalSecrets)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	messages := syncmap.Map{}
 | 
						messages := syncmap.Map{}
 | 
				
			||||||
	send := func(seq int, dst, msg []byte) error {
 | 
						send := func(peer []byte) func(seq int, dst, msg []byte) error {
 | 
				
			||||||
		fmt.Printf("send %d bytes for seq %d to %+x\n", len(msg), seq, dst)
 | 
							return func(seq int, dst, msg []byte) error {
 | 
				
			||||||
 | 
								fmt.Printf("send %d bytes for seq %d to %+x\n", len(msg), seq, dst)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		b := byte(seq)
 | 
								b := byte(seq)
 | 
				
			||||||
		dst = append(append([]byte{}, b), dst...)
 | 
								dst = append(append(append([]byte{}, b), peer...), dst...)
 | 
				
			||||||
		if msg == nil {
 | 
								if msg == nil {
 | 
				
			||||||
			msg = []byte{0x01}
 | 
									msg = []byte{0x01}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								messages.Store(string(dst), string(msg))
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		messages.Store(string(dst), string(msg))
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	recv := func(seq int, src []byte) ([]byte, error) {
 | 
						recv := func(peer []byte) func(seq int, src []byte) ([]byte, error) {
 | 
				
			||||||
		fmt.Printf("recv %d from %+x\n", seq, src)
 | 
							return func(seq int, src []byte) ([]byte, error) {
 | 
				
			||||||
 | 
								fmt.Printf("recv %d from %+x\n", seq, src)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		b := byte(seq)
 | 
								b := byte(seq)
 | 
				
			||||||
		bsrc := append(append([]byte{}, b), src...)
 | 
								bsrc := append(append(append([]byte{}, b), src...), peer...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		msg, ok := messages.LoadAndDelete(string(bsrc))
 | 
								msg, ok := messages.LoadAndDelete(string(bsrc))
 | 
				
			||||||
		for !ok {
 | 
								for !ok {
 | 
				
			||||||
			fmt.Printf("no message yet, waiting for recv %d from %+x\n", seq, src)
 | 
									fmt.Printf("no message yet, waiting for recv %d from %+x\n", seq, src)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			time.Sleep(100 * time.Millisecond)
 | 
									time.Sleep(100 * time.Millisecond)
 | 
				
			||||||
			msg, ok = messages.LoadAndDelete(string(bsrc))
 | 
									msg, ok = messages.LoadAndDelete(string(bsrc))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return []byte(msg.(string)), nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		return []byte(msg.(string)), nil
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for j := 1; j < 4; j++ {
 | 
						for j := 1; j < 4; j++ {
 | 
				
			||||||
@ -244,8 +247,8 @@ func TestProcessRound(t *testing.T) {
 | 
				
			|||||||
					idkPoints,
 | 
										idkPoints,
 | 
				
			||||||
					peerSecrets[i],
 | 
										peerSecrets[i],
 | 
				
			||||||
					curves.BLS48581G1(),
 | 
										curves.BLS48581G1(),
 | 
				
			||||||
					send,
 | 
										send(peerPoints[i]),
 | 
				
			||||||
					recv,
 | 
										recv(peerPoints[i]),
 | 
				
			||||||
					[]byte{0x01},
 | 
										[]byte{0x01},
 | 
				
			||||||
				)
 | 
									)
 | 
				
			||||||
				require.NoError(t, err)
 | 
									require.NoError(t, err)
 | 
				
			||||||
 | 
				
			|||||||
@ -45,6 +45,8 @@ type CeremonyExecutionEngine struct {
 | 
				
			|||||||
	activeClockFrame           *protobufs.ClockFrame
 | 
						activeClockFrame           *protobufs.ClockFrame
 | 
				
			||||||
	alreadyPublishedShare      bool
 | 
						alreadyPublishedShare      bool
 | 
				
			||||||
	alreadyPublishedTranscript bool
 | 
						alreadyPublishedTranscript bool
 | 
				
			||||||
 | 
						seenMessageMap             map[string]bool
 | 
				
			||||||
 | 
						seenMessageMx              sync.Mutex
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewCeremonyExecutionEngine(
 | 
					func NewCeremonyExecutionEngine(
 | 
				
			||||||
@ -71,6 +73,8 @@ func NewCeremonyExecutionEngine(
 | 
				
			|||||||
		participantMx:         sync.Mutex{},
 | 
							participantMx:         sync.Mutex{},
 | 
				
			||||||
		peerChannels:          map[string]*p2p.PublicP2PChannel{},
 | 
							peerChannels:          map[string]*p2p.PublicP2PChannel{},
 | 
				
			||||||
		alreadyPublishedShare: false,
 | 
							alreadyPublishedShare: false,
 | 
				
			||||||
 | 
							seenMessageMx:         sync.Mutex{},
 | 
				
			||||||
 | 
							seenMessageMap:        map[string]bool{},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	provingKey, _, publicKeyBytes, provingKeyAddress := e.clock.GetProvingKey(
 | 
						provingKey, _, publicKeyBytes, provingKeyAddress := e.clock.GetProvingKey(
 | 
				
			||||||
@ -329,7 +333,17 @@ func (e *CeremonyExecutionEngine) RunWorker() {
 | 
				
			|||||||
				zap.Uint64("current_round", app.RoundCount),
 | 
									zap.Uint64("current_round", app.RoundCount),
 | 
				
			||||||
			)
 | 
								)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			e.ensureSecrets(app)
 | 
								if len(e.activeSecrets) == 0 {
 | 
				
			||||||
 | 
									// If we ended up in the scenario where we do not have any secrets
 | 
				
			||||||
 | 
									// available but we're in the round, we should politely leave.
 | 
				
			||||||
 | 
									for _, p := range app.ActiveParticipants {
 | 
				
			||||||
 | 
										if bytes.Equal(p.KeyValue, e.proverPublicKey) {
 | 
				
			||||||
 | 
											e.publishDroppedParticipant(e.proverPublicKey)
 | 
				
			||||||
 | 
											break
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			shouldConnect := false
 | 
								shouldConnect := false
 | 
				
			||||||
			position := 0
 | 
								position := 0
 | 
				
			||||||
@ -339,6 +353,7 @@ func (e *CeremonyExecutionEngine) RunWorker() {
 | 
				
			|||||||
					if bytes.Equal(p.KeyValue, e.proverPublicKey) {
 | 
										if bytes.Equal(p.KeyValue, e.proverPublicKey) {
 | 
				
			||||||
						shouldConnect = true
 | 
											shouldConnect = true
 | 
				
			||||||
						position = i
 | 
											position = i
 | 
				
			||||||
 | 
											break
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -378,6 +393,7 @@ func (e *CeremonyExecutionEngine) RunWorker() {
 | 
				
			|||||||
					err := e.participateRound(app)
 | 
										err := e.participateRound(app)
 | 
				
			||||||
					if err != nil {
 | 
										if err != nil {
 | 
				
			||||||
						e.logger.Error("error while participating in round", zap.Error(err))
 | 
											e.logger.Error("error while participating in round", zap.Error(err))
 | 
				
			||||||
 | 
											e.publishDroppedParticipant(e.proverPublicKey)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else if len(app.ActiveParticipants) == 1 &&
 | 
								} else if len(app.ActiveParticipants) == 1 &&
 | 
				
			||||||
@ -411,7 +427,19 @@ func (e *CeremonyExecutionEngine) RunWorker() {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !e.alreadyPublishedShare {
 | 
								shouldPublish := false
 | 
				
			||||||
 | 
								for _, p := range app.ActiveParticipants {
 | 
				
			||||||
 | 
									if bytes.Equal(p.KeyValue, e.proverPublicKey) {
 | 
				
			||||||
 | 
										shouldPublish = true
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if !e.alreadyPublishedShare && shouldPublish {
 | 
				
			||||||
 | 
									if len(e.activeSecrets) == 0 {
 | 
				
			||||||
 | 
										e.publishDroppedParticipant(e.proverPublicKey)
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				err := e.publishTranscriptShare(app)
 | 
									err := e.publishTranscriptShare(app)
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					e.logger.Error(
 | 
										e.logger.Error(
 | 
				
			||||||
@ -620,8 +648,14 @@ func (e *CeremonyExecutionEngine) participateRound(
 | 
				
			|||||||
		return errors.Wrap(err, "participate round")
 | 
							return errors.Wrap(err, "participate round")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spk, err := e.keyManager.GetAgreementKey("q-ratchet-spk")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errors.Wrap(err, "participate round")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	idkPoint := curves.ED448().Point.Generator().Mul(idk)
 | 
						idkPoint := curves.ED448().Point.Generator().Mul(idk)
 | 
				
			||||||
	idks := []curves.Point{}
 | 
						idks := []curves.Point{}
 | 
				
			||||||
 | 
						initiator := false
 | 
				
			||||||
	for _, p := range app.ActiveParticipants {
 | 
						for _, p := range app.ActiveParticipants {
 | 
				
			||||||
		if !bytes.Equal(p.KeyValue, e.proverPublicKey) {
 | 
							if !bytes.Equal(p.KeyValue, e.proverPublicKey) {
 | 
				
			||||||
			ic, err := e.keyStore.GetLatestKeyBundle(p.KeyValue)
 | 
								ic, err := e.keyStore.GetLatestKeyBundle(p.KeyValue)
 | 
				
			||||||
@ -647,8 +681,35 @@ func (e *CeremonyExecutionEngine) participateRound(
 | 
				
			|||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return errors.Wrap(err, "participate round")
 | 
									return errors.Wrap(err, "participate round")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								receiverSpk, err := curves.ED448().Point.FromAffineCompressed(
 | 
				
			||||||
 | 
									kba.SignedPreKey.GetPublicKeySignatureEd448().PublicKey.KeyValue,
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return errors.Wrap(err, "participate round")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if _, ok := e.peerChannels[string(p.KeyValue)]; !ok {
 | 
				
			||||||
 | 
									e.peerChannels[string(p.KeyValue)], err = p2p.NewPublicP2PChannel(
 | 
				
			||||||
 | 
										e.proverPublicKey,
 | 
				
			||||||
 | 
										p.KeyValue,
 | 
				
			||||||
 | 
										initiator,
 | 
				
			||||||
 | 
										idk,
 | 
				
			||||||
 | 
										spk,
 | 
				
			||||||
 | 
										receiverIdk,
 | 
				
			||||||
 | 
										receiverSpk,
 | 
				
			||||||
 | 
										curves.ED448(),
 | 
				
			||||||
 | 
										e.keyManager,
 | 
				
			||||||
 | 
										e.pubSub,
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return errors.Wrap(err, "participate round")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			idks = append(idks, receiverIdk)
 | 
								idks = append(idks, receiverIdk)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
 | 
								initiator = true
 | 
				
			||||||
			idks = append(idks, idkPoint)
 | 
								idks = append(idks, idkPoint)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -666,19 +727,19 @@ func (e *CeremonyExecutionEngine) participateRound(
 | 
				
			|||||||
		idks,
 | 
							idks,
 | 
				
			||||||
		e.activeSecrets,
 | 
							e.activeSecrets,
 | 
				
			||||||
		curves.BLS48581G1(),
 | 
							curves.BLS48581G1(),
 | 
				
			||||||
		func(i int, filter, msg []byte) error {
 | 
							func(i int, receiver []byte, msg []byte) error {
 | 
				
			||||||
			return e.peerChannels[string(filter[len(e.proverPublicKey):])].Send(msg)
 | 
								return e.peerChannels[string(receiver)].Send(msg)
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		func(i int, filter []byte) ([]byte, error) {
 | 
							func(i int, sender []byte) ([]byte, error) {
 | 
				
			||||||
			msg, err := e.peerChannels[string(
 | 
								msg, err := e.peerChannels[string(
 | 
				
			||||||
				filter[:len(e.proverPublicKey)],
 | 
									sender,
 | 
				
			||||||
			)].Receive()
 | 
								)].Receive()
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				e.publishDroppedParticipant(filter[:len(e.proverPublicKey)])
 | 
									e.publishDroppedParticipant(sender)
 | 
				
			||||||
				return nil, err
 | 
									return nil, err
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				if i == 0 {
 | 
									if i == 0 {
 | 
				
			||||||
					e.publishLastSeenParticipant(filter[:len(e.proverPublicKey)])
 | 
										e.publishLastSeenParticipant(sender)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return msg, nil
 | 
									return msg, nil
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user