fix: Prevent (reject event <-> resend event) loop (#4055)
This commit is contained in:
parent
0f065a9f07
commit
2b53d71708
|
@ -1425,6 +1425,8 @@ func (m *Manager) HandleCommunityEventsMessage(signer *ecdsa.PublicKey, message
|
|||
err = community.UpdateCommunityByEvents(eventsMessage)
|
||||
if err != nil {
|
||||
if err == ErrInvalidCommunityEventClock && community.IsControlNode() {
|
||||
// send updated CommunityDescription to the event sender on top of which he must apply his changes
|
||||
eventsMessage.EventsBaseCommunityDescription = community.config.CommunityDescriptionProtocolMessage
|
||||
m.publish(&Subscription{
|
||||
CommunityEventsMessageInvalidClock: &CommunityEventsMessageInvalidClockSignal{
|
||||
Community: community,
|
||||
|
@ -1491,6 +1493,17 @@ func (m *Manager) HandleCommunityEventsMessageRejected(signer *ecdsa.PublicKey,
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
communityDescription, err := validateAndGetEventsMessageCommunityDescription(eventsMessage.EventsBaseCommunityDescription, signer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// the privileged member did not receive updated CommunityDescription so his events
|
||||
// will be send on top of outdated CommunityDescription
|
||||
if communityDescription.Clock != community.Clock() {
|
||||
return nil, errors.New("resend rejected community events aborted, client node has outdated community description")
|
||||
}
|
||||
|
||||
eventsMessage.Events = m.validateAndFilterEvents(community, eventsMessage.Events)
|
||||
|
||||
myRejectedEvents := make([]CommunityEvent, 0)
|
||||
|
@ -4813,3 +4826,7 @@ func (m *Manager) shareAcceptedRequestToJoinWithPrivilegedMembers(community *Com
|
|||
func (m *Manager) GetCommunityRequestsToJoinWithRevealedAddresses(communityID types.HexBytes) ([]*RequestToJoin, error) {
|
||||
return m.persistence.GetCommunityRequestsToJoinWithRevealedAddresses(communityID)
|
||||
}
|
||||
|
||||
func (m *Manager) SaveCommunity(community *Community) error {
|
||||
return m.persistence.SaveCommunity(community)
|
||||
}
|
||||
|
|
|
@ -381,3 +381,62 @@ func (s *AdminCommunityEventsSuite) TestReceiveRequestsToJoinWithRevealedAccount
|
|||
bob := s.newMessenger(accountPassword, []string{bobAccountAddress})
|
||||
testMemberReceiveRequestsToJoinAfterGettingNewRole(s, bob, protobuf.CommunityTokenPermission_BECOME_ADMIN)
|
||||
}
|
||||
|
||||
func (s *AdminCommunityEventsSuite) TestAdminDoesNotHaveRejectedEventsLoop() {
|
||||
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN)
|
||||
|
||||
// admin modifies community description
|
||||
adminEditRequest := &requests.EditCommunity{
|
||||
CommunityID: community.ID(),
|
||||
CreateCommunity: requests.CreateCommunity{
|
||||
Name: "admin name",
|
||||
Description: "admin description",
|
||||
Color: "#FFFFFF",
|
||||
Membership: protobuf.CommunityPermissions_ON_REQUEST,
|
||||
},
|
||||
}
|
||||
_, err := s.admin.EditCommunity(adminEditRequest)
|
||||
s.Require().NoError(err)
|
||||
|
||||
community, err = s.owner.communitiesManager.GetByID(community.ID())
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Update community clock without publishing new CommunityDescription
|
||||
err = community.DeclineRequestToJoin(nil)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = s.owner.communitiesManager.SaveCommunity(community)
|
||||
s.Require().NoError(err)
|
||||
|
||||
waitOnAdminEventsRejection := waitOnCommunitiesEvent(s.owner, func(s *communities.Subscription) bool {
|
||||
return s.CommunityEventsMessageInvalidClock != nil
|
||||
})
|
||||
|
||||
// control node receives admin event and rejects it
|
||||
_, err = WaitOnMessengerResponse(s.owner, func(response *MessengerResponse) bool {
|
||||
select {
|
||||
case err := <-waitOnAdminEventsRejection:
|
||||
s.Require().NoError(err)
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}, "")
|
||||
s.Require().NoError(err)
|
||||
|
||||
community, err = s.owner.communitiesManager.GetByID(community.ID())
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEqual(adminEditRequest.Description, community.DescriptionText())
|
||||
|
||||
// admin receives rejected events and re-applies them
|
||||
// there is no signal whatsoever, we just wait for admin to process all incoming messages
|
||||
_, _ = WaitOnMessengerResponse(s.admin, func(response *MessengerResponse) bool {
|
||||
return false
|
||||
}, "")
|
||||
|
||||
// control node does not receives admin event
|
||||
_, err = WaitOnMessengerResponse(s.owner, func(response *MessengerResponse) bool {
|
||||
return len(response.Communities()) > 0
|
||||
}, "no communities in response")
|
||||
s.Require().Error(err)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue