github.com/status-im/status-go@v1.1.0/protocol/messenger_community_storenodes.go (about) 1 package protocol 2 3 import ( 4 "context" 5 "errors" 6 7 "github.com/golang/protobuf/proto" 8 "go.uber.org/zap" 9 10 "github.com/status-im/status-go/eth-node/crypto" 11 "github.com/status-im/status-go/eth-node/types" 12 "github.com/status-im/status-go/protocol/common" 13 "github.com/status-im/status-go/protocol/communities" 14 "github.com/status-im/status-go/protocol/protobuf" 15 "github.com/status-im/status-go/protocol/storenodes" 16 v1protocol "github.com/status-im/status-go/protocol/v1" 17 ) 18 19 func (m *Messenger) sendCommunityPublicStorenodesInfo(community *communities.Community, snodes storenodes.Storenodes) error { 20 if !community.IsControlNode() { 21 return communities.ErrNotControlNode 22 } 23 24 clock, _ := m.getLastClockWithRelatedChat() 25 pb := &protobuf.CommunityStorenodes{ 26 Clock: clock, 27 CommunityId: community.ID(), 28 Storenodes: snodes.ToProtobuf(), 29 ChainId: communities.CommunityDescriptionTokenOwnerChainID(community.Description()), 30 } 31 snPayload, err := proto.Marshal(pb) 32 if err != nil { 33 return err 34 } 35 signature, err := crypto.Sign(crypto.Keccak256(snPayload), community.PrivateKey()) 36 if err != nil { 37 return err 38 } 39 signedStorenodesInfo := &protobuf.CommunityPublicStorenodesInfo{ 40 Signature: signature, 41 Payload: snPayload, 42 } 43 signedPayload, err := proto.Marshal(signedStorenodesInfo) 44 if err != nil { 45 return err 46 } 47 48 rawMessage := common.RawMessage{ 49 Payload: signedPayload, 50 Sender: community.PrivateKey(), 51 SkipEncryptionLayer: true, 52 MessageType: protobuf.ApplicationMetadataMessage_COMMUNITY_PUBLIC_STORENODES_INFO, 53 PubsubTopic: community.PubsubTopic(), 54 Priority: &common.HighPriority, 55 } 56 57 _, err = m.sender.SendPublic(context.Background(), community.IDString(), rawMessage) 58 return err 59 } 60 61 // HandleCommunityPublicStorenodesInfo will process the control message sent by the community owner on updating the community storenodes for his community (sendCommunityPublicStorenodesInfo). 62 // The message will be received by many peers that are not interested on that community, so if we don't have this community in our DB we just ignore this message. 63 func (m *Messenger) HandleCommunityPublicStorenodesInfo(state *ReceivedMessageState, a *protobuf.CommunityPublicStorenodesInfo, statusMessage *v1protocol.StatusMessage) error { 64 sn := &protobuf.CommunityStorenodes{} 65 err := proto.Unmarshal(a.Payload, sn) 66 if err != nil { 67 return err 68 } 69 logger := m.logger.Named("HandleCommunityPublicStorenodesInfo").With(zap.String("communityID", types.EncodeHex(sn.CommunityId))) 70 71 err = m.verifyCommunitySignature(a.Payload, a.Signature, sn.CommunityId, sn.ChainId) 72 if err != nil { 73 logger.Error("failed to verify community signature", zap.Error(err)) 74 return err 75 } 76 77 // verify if we are interested in this control message 78 _, err = m.communitiesManager.GetByID(sn.CommunityId) 79 if err != nil { 80 if errors.Is(err, communities.ErrOrgNotFound) { 81 logger.Debug("ignoring control message, community not found") 82 return nil 83 } 84 logger.Error("failed get community by id", zap.Error(err)) 85 return err 86 } 87 88 if err := m.communityStorenodes.UpdateStorenodesInDB(sn.CommunityId, storenodes.FromProtobuf(sn.Storenodes, sn.Clock), sn.Clock); err != nil { 89 logger.Error("failed to update storenodes for community", zap.Error(err)) 90 return err 91 } 92 return nil 93 }