mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-11-20 15:15:18 +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