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  }