status-go/protocol/communities_messenger_share...

1155 lines
48 KiB
Go
Raw Normal View History

package protocol
import (
"testing"
"time"
"github.com/stretchr/testify/suite"
"go.uber.org/zap"
gethcommon "github.com/ethereum/go-ethereum/common"
hexutil "github.com/ethereum/go-ethereum/common/hexutil"
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/communities"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/requests"
"github.com/status-im/status-go/protocol/tt"
)
func TestMessengerCommunitiesSharedMemberAddressSuite(t *testing.T) {
suite.Run(t, new(MessengerCommunitiesSharedMemberAddressSuite))
}
type MessengerCommunitiesSharedMemberAddressSuite struct {
suite.Suite
owner *Messenger
bob *Messenger
alice *Messenger
ownerWaku types.Waku
bobWaku types.Waku
aliceWaku types.Waku
logger *zap.Logger
mockedBalances map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big // chainID, account, token, balance
collectiblesServiceMock *CollectiblesServiceMock
mockedCollectibles communities.CollectiblesByChain
collectiblesManagerMock CollectiblesManagerMock
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) SetupTest() {
// Initialize with nil to avoid panics in TearDownTest
s.owner = nil
s.bob = nil
s.alice = nil
s.ownerWaku = nil
s.bobWaku = nil
s.aliceWaku = nil
communities.SetValidateInterval(300 * time.Millisecond)
s.collectiblesServiceMock = &CollectiblesServiceMock{}
s.mockedCollectibles = communities.CollectiblesByChain{}
s.collectiblesManagerMock = CollectiblesManagerMock{
Collectibles: &s.mockedCollectibles,
}
s.resetMockedBalances()
s.logger = tt.MustCreateTestLogger()
wakuNodes := CreateWakuV2Network(&s.Suite, s.logger, []string{"owner", "bob", "alice"})
s.ownerWaku = wakuNodes[0]
s.owner = s.newMessenger(ownerPassword, []string{ownerAddress}, s.ownerWaku, "owner", []Option{})
s.bobWaku = wakuNodes[1]
s.bob = s.newMessenger(bobPassword, []string{bobAddress}, s.bobWaku, "bob", []Option{})
s.bob.EnableBackedupMessagesProcessing()
s.aliceWaku = wakuNodes[2]
s.alice = s.newMessenger(alicePassword, []string{aliceAddress1, aliceAddress2}, s.aliceWaku, "alice", []Option{})
_, err := s.owner.Start()
s.Require().NoError(err)
_, err = s.bob.Start()
s.Require().NoError(err)
_, err = s.alice.Start()
s.Require().NoError(err)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TearDownTest() {
TearDownMessenger(&s.Suite, s.owner)
TearDownMessenger(&s.Suite, s.bob)
TearDownMessenger(&s.Suite, s.alice)
if s.ownerWaku != nil {
s.Require().NoError(gethbridge.GetGethWakuV2From(s.ownerWaku).Stop())
}
if s.bobWaku != nil {
s.Require().NoError(gethbridge.GetGethWakuV2From(s.bobWaku).Stop())
}
if s.aliceWaku != nil {
s.Require().NoError(gethbridge.GetGethWakuV2From(s.aliceWaku).Stop())
}
_ = s.logger.Sync()
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) newMessenger(password string, walletAddresses []string, waku types.Waku, name string, extraOptions []Option) *Messenger {
communityManagerOptions := []communities.ManagerOption{
communities.WithAllowForcingCommunityMembersReevaluation(true),
}
extraOptions = append(extraOptions, WithCommunityManagerOptions(communityManagerOptions))
return newTestCommunitiesMessenger(&s.Suite, waku, testCommunitiesMessengerConfig{
testMessengerConfig: testMessengerConfig{
logger: s.logger.Named(name),
extraOptions: extraOptions,
},
password: password,
walletAddresses: walletAddresses,
mockedBalances: &s.mockedBalances,
collectiblesService: s.collectiblesServiceMock,
collectiblesManager: &s.collectiblesManagerMock,
})
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) joinCommunity(community *communities.Community, user *Messenger, password string, addresses []string) {
joinCommunity(&s.Suite, community.ID(), s.owner, user, password, addresses)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) checkRevealedAccounts(communityID types.HexBytes, user *Messenger, expectedAccounts []*protobuf.RevealedAccount) {
revealedAccounts, err := user.communitiesManager.GetRevealedAddresses(communityID, s.alice.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Equal(revealedAccounts, expectedAccounts)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) makeAddressSatisfyTheCriteria(chainID uint64, address string, criteria *protobuf.TokenCriteria) {
makeAddressSatisfyTheCriteria(&s.Suite, s.mockedBalances, s.mockedCollectibles, chainID, address, criteria)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) resetMockedBalances() {
s.mockedBalances = make(map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big)
s.mockedBalances[testChainID1] = make(map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big)
s.mockedBalances[testChainID1][gethcommon.HexToAddress(aliceAddress1)] = make(map[gethcommon.Address]*hexutil.Big)
s.mockedBalances[testChainID1][gethcommon.HexToAddress(aliceAddress2)] = make(map[gethcommon.Address]*hexutil.Big)
s.mockedBalances[testChainID1][gethcommon.HexToAddress(bobAddress)] = make(map[gethcommon.Address]*hexutil.Big)
}
func createTokenMasterTokenCriteria() *protobuf.TokenCriteria {
return &protobuf.TokenCriteria{
ContractAddresses: map[uint64]string{testChainID1: "0x123"},
Type: protobuf.CommunityTokenType_ERC20,
Symbol: "STT",
Name: "Status Test Token",
AmountInWei: "10000000000000000000",
Decimals: 18,
}
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) createEditSharedAddressesRequest(communityID types.HexBytes) *requests.EditSharedAddresses {
request := &requests.EditSharedAddresses{CommunityID: communityID, AddressesToReveal: []string{aliceAddress2}, AirdropAddress: aliceAddress2}
signingParams, err := s.alice.GenerateJoiningCommunityRequestsForSigning(common.PubkeyToHex(&s.alice.identity.PublicKey), communityID, request.AddressesToReveal)
s.Require().NoError(err)
passwdHash := types.EncodeHex(crypto.Keccak256([]byte(alicePassword)))
for i := range signingParams {
signingParams[i].Password = passwdHash
}
signatures, err := s.alice.SignData(signingParams)
s.Require().NoError(err)
updateAddresses := len(request.AddressesToReveal) == 0
if updateAddresses {
request.AddressesToReveal = make([]string, len(signingParams))
}
for i := range signingParams {
request.AddressesToReveal[i] = signingParams[i].Address
request.Signatures = append(request.Signatures, types.FromHex(signatures[i]))
}
if updateAddresses {
request.AirdropAddress = request.AddressesToReveal[0]
}
return request
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) joinOnRequestCommunityAsTokenMaster(community *communities.Community) {
bobRequest := createRequestToJoinCommunity(&s.Suite, community.ID(), s.bob, bobPassword, []string{bobAddress})
requestToJoinID := requestToJoinCommunity(&s.Suite, s.owner, s.bob, bobRequest)
// accept join request
acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: requestToJoinID}
response, err := s.owner.AcceptRequestToJoinCommunity(acceptRequestToJoin)
s.Require().NoError(err)
s.Require().NotNil(response)
updatedCommunity := response.Communities()[0]
s.Require().NotNil(updatedCommunity)
s.Require().True(updatedCommunity.HasMember(&s.bob.identity.PublicKey))
s.Require().True(updatedCommunity.IsMemberTokenMaster(&s.bob.identity.PublicKey))
// receive request to join response
_, err = WaitOnMessengerResponse(
s.bob,
func(r *MessengerResponse) bool {
return len(r.Communities()) > 0 &&
r.Communities()[0].HasMember(&s.bob.identity.PublicKey) &&
r.Communities()[0].IsMemberTokenMaster(&s.bob.identity.PublicKey)
},
"user did not receive request to join response",
)
s.Require().NoError(err)
userCommunity, err := s.bob.GetCommunityByID(community.ID())
s.Require().NoError(err)
s.Require().True(userCommunity.HasMember(&s.bob.identity.PublicKey))
s.Require().True(userCommunity.IsTokenMaster())
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) waitForRevealedAddresses(receiver *Messenger, communityID types.HexBytes, expectedAccounts []*protobuf.RevealedAccount) {
_, err := WaitOnMessengerResponse(receiver, func(r *MessengerResponse) bool {
revealedAccounts, err := receiver.communitiesManager.GetRevealedAddresses(communityID, s.alice.IdentityPublicKeyString())
if err != nil {
return false
}
if len(expectedAccounts) != len(revealedAccounts) {
return false
}
for index := range revealedAccounts {
if revealedAccounts[index].Address != expectedAccounts[index].Address {
return false
}
}
return true
}, "client did not receive alice shared address")
s.Require().NoError(err)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestJoinedCommunityMembersSharedAddress() {
community, _ := createCommunity(&s.Suite, s.owner)
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
s.joinCommunity(community, s.alice, alicePassword, []string{})
s.joinCommunity(community, s.bob, bobPassword, []string{})
community, err := s.owner.GetCommunityByID(community.ID())
s.Require().NoError(err)
s.Require().Equal(3, community.MembersCount())
// Check owner's DB for revealed accounts
for pubKey := range community.Members() {
if pubKey != common.PubkeyToHex(&s.owner.identity.PublicKey) {
revealedAccounts, err := s.owner.communitiesManager.GetRevealedAddresses(community.ID(), pubKey)
s.Require().NoError(err)
switch pubKey {
case common.PubkeyToHex(&s.alice.identity.PublicKey):
s.Require().Len(revealedAccounts, 2)
s.Require().Equal(revealedAccounts[0].Address, aliceAddress1)
s.Require().Equal(revealedAccounts[1].Address, aliceAddress2)
s.Require().Equal(true, revealedAccounts[0].IsAirdropAddress)
case common.PubkeyToHex(&s.bob.identity.PublicKey):
s.Require().Len(revealedAccounts, 1)
s.Require().Equal(revealedAccounts[0].Address, bobAddress)
s.Require().Equal(true, revealedAccounts[0].IsAirdropAddress)
default:
s.Require().Fail("pubKey does not match expected keys")
}
}
}
// Check Bob's DB for revealed accounts
revealedAccountsInBobsDB, err := s.bob.communitiesManager.GetRevealedAddresses(community.ID(), common.PubkeyToHex(&s.bob.identity.PublicKey))
s.Require().NoError(err)
s.Require().Len(revealedAccountsInBobsDB, 1)
s.Require().Equal(revealedAccountsInBobsDB[0].Address, bobAddress)
s.Require().Equal(true, revealedAccountsInBobsDB[0].IsAirdropAddress)
// Check Alices's DB for revealed accounts
revealedAccountsInAlicesDB, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), common.PubkeyToHex(&s.alice.identity.PublicKey))
s.Require().NoError(err)
s.Require().Len(revealedAccountsInAlicesDB, 2)
s.Require().Equal(revealedAccountsInAlicesDB[0].Address, aliceAddress1)
s.Require().Equal(revealedAccountsInAlicesDB[1].Address, aliceAddress2)
s.Require().Equal(true, revealedAccountsInAlicesDB[0].IsAirdropAddress)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestJoinedCommunityMembersSelectedSharedAddress() {
community, _ := createCommunity(&s.Suite, s.owner)
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
s.joinCommunity(community, s.alice, alicePassword, []string{aliceAddress2})
community, err := s.owner.GetCommunityByID(community.ID())
s.Require().NoError(err)
s.Require().Equal(2, community.MembersCount())
alicePubkey := common.PubkeyToHex(&s.alice.identity.PublicKey)
// Check Alice's DB for revealed accounts
revealedAccountsInAlicesDB, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), alicePubkey)
s.Require().NoError(err)
s.Require().Len(revealedAccountsInAlicesDB, 1)
s.Require().Equal(revealedAccountsInAlicesDB[0].Address, aliceAddress2)
s.Require().Equal(true, revealedAccountsInAlicesDB[0].IsAirdropAddress)
// Check owner's DB for revealed accounts
s.checkRevealedAccounts(community.ID(), s.owner, revealedAccountsInAlicesDB)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestJoinedCommunityMembersMultipleSelectedSharedAddresses() {
community, _ := createCommunity(&s.Suite, s.owner)
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
s.joinCommunity(community, s.alice, alicePassword, []string{aliceAddress1, aliceAddress2})
community, err := s.owner.GetCommunityByID(community.ID())
s.Require().NoError(err)
s.Require().Equal(2, community.MembersCount())
alicePubkey := common.PubkeyToHex(&s.alice.identity.PublicKey)
// Check Alice's DB for revealed accounts
revealedAccountsInAlicesDB, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), alicePubkey)
s.Require().NoError(err)
s.Require().Len(revealedAccountsInAlicesDB, 2)
s.Require().Equal(revealedAccountsInAlicesDB[0].Address, aliceAddress1)
s.Require().Equal(revealedAccountsInAlicesDB[1].Address, aliceAddress2)
s.Require().Equal(true, revealedAccountsInAlicesDB[0].IsAirdropAddress)
// Check owner's DB for revealed accounts
s.checkRevealedAccounts(community.ID(), s.owner, revealedAccountsInAlicesDB)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestEditSharedAddresses() {
community, _ := createCommunity(&s.Suite, s.owner)
alicePubkey := common.PubkeyToHex(&s.alice.identity.PublicKey)
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
s.joinCommunity(community, s.alice, alicePassword, []string{aliceAddress1})
community, err := s.owner.GetCommunityByID(community.ID())
s.Require().NoError(err)
s.Require().Equal(2, community.MembersCount())
aliceExpectedRevealedAccounts, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), alicePubkey)
s.Require().NoError(err)
s.Require().Len(aliceExpectedRevealedAccounts, 1)
s.Require().Equal(aliceExpectedRevealedAccounts[0].Address, aliceAddress1)
s.Require().Equal(true, aliceExpectedRevealedAccounts[0].IsAirdropAddress)
s.checkRevealedAccounts(community.ID(), s.owner, aliceExpectedRevealedAccounts)
request := s.createEditSharedAddressesRequest(community.ID())
response, err := s.alice.EditSharedAddressesForCommunity(request)
s.Require().NoError(err)
s.Require().NotNil(response)
aliceExpectedRevealedAccounts, err = s.alice.communitiesManager.GetRevealedAddresses(community.ID(), alicePubkey)
s.Require().NoError(err)
s.Require().Len(aliceExpectedRevealedAccounts, 1)
s.Require().Equal(aliceExpectedRevealedAccounts[0].Address, aliceAddress2)
s.Require().Equal(true, aliceExpectedRevealedAccounts[0].IsAirdropAddress)
// check that owner received revealed address
s.waitForRevealedAddresses(s.owner, community.ID(), aliceExpectedRevealedAccounts)
// check that we filter out outdated edit shared addresses events
community, err = s.owner.GetCommunityByID(community.ID())
s.Require().NoError(err)
aliceClock := community.Description().Members[s.alice.IdentityPublicKeyString()].LastUpdateClock
s.Require().Greater(aliceClock, uint64(1))
editMsg := &protobuf.CommunityEditSharedAddresses{
Clock: aliceClock - 1,
CommunityId: community.ID(),
RevealedAccounts: aliceExpectedRevealedAccounts,
}
state := &ReceivedMessageState{
CurrentMessageState: &CurrentMessageState{
PublicKey: s.alice.IdentityPublicKey(),
},
}
err = s.owner.HandleCommunityEditSharedAddresses(state, editMsg, nil)
s.Require().Error(err, communities.ErrEditSharedAddressesRequestOutdated)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterReceivesEditedSharedAddresses() {
community, _ := createCommunity(&s.Suite, s.owner)
alicePubkey := s.alice.IdentityPublicKeyString()
tokenCriteria := createTokenMasterTokenCriteria()
_, err := s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{
CommunityID: community.ID(),
Type: protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER,
TokenCriteria: []*protobuf.TokenCriteria{tokenCriteria},
})
s.Require().NoError(err)
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
s.joinCommunity(community, s.alice, alicePassword, []string{aliceAddress1})
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
// make bob satisfy the Token Master criteria
s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, tokenCriteria)
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
s.joinCommunity(community, s.bob, bobPassword, []string{bobAddress})
// check bob has TM role
community, err = s.bob.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
checkRoleBasedOnThePermissionType(protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER, &s.bob.identity.PublicKey, community)
s.Require().NoError(err)
expectedAliceRevealedAccounts, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Len(expectedAliceRevealedAccounts, 1)
s.waitForRevealedAddresses(s.bob, community.ID(), expectedAliceRevealedAccounts)
request := s.createEditSharedAddressesRequest(community.ID())
response, err := s.alice.EditSharedAddressesForCommunity(request)
s.Require().NoError(err)
s.Require().NotNil(response)
expectedAliceRevealedAccounts, err = s.alice.communitiesManager.GetRevealedAddresses(community.ID(), alicePubkey)
s.Require().NoError(err)
s.Require().Len(expectedAliceRevealedAccounts, 1)
s.Require().Equal(expectedAliceRevealedAccounts[0].Address, aliceAddress2)
s.Require().Equal(true, expectedAliceRevealedAccounts[0].IsAirdropAddress)
s.waitForRevealedAddresses(s.owner, community.ID(), expectedAliceRevealedAccounts)
s.Require().NoError(err)
s.waitForRevealedAddresses(s.bob, community.ID(), expectedAliceRevealedAccounts)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestSharedAddressesReturnsRevealedAccount() {
community, _ := createCommunity(&s.Suite, s.owner)
permissionRequest := requests.CreateCommunityTokenPermission{
CommunityID: community.ID(),
Type: protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL,
TokenCriteria: []*protobuf.TokenCriteria{
&protobuf.TokenCriteria{
Type: protobuf.CommunityTokenType_ERC20,
ContractAddresses: map[uint64]string{testChainID1: "0x123"},
Symbol: "TEST",
AmountInWei: "100000000000000000000",
Decimals: uint64(18),
},
},
}
response, err := s.owner.CreateCommunityTokenPermission(&permissionRequest)
s.Require().NoError(err)
s.Require().Len(response.Communities(), 1)
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
s.joinCommunity(community, s.alice, alicePassword, []string{})
revealedAccounts, err := s.alice.GetRevealedAccounts(community.ID(), common.PubkeyToHex(&s.alice.identity.PublicKey))
s.Require().NoError(err)
revealedAddressesMap := make(map[string]struct{}, len(revealedAccounts))
for _, acc := range revealedAccounts {
revealedAddressesMap[acc.Address] = struct{}{}
}
s.Require().Len(revealedAddressesMap, 2)
s.Require().Contains(revealedAddressesMap, aliceAddress1)
s.Require().Contains(revealedAddressesMap, aliceAddress2)
sharedAddresses, err := s.alice.getSharedAddresses(community.ID(), []string{})
s.Require().NoError(err)
s.Require().Len(sharedAddresses, 2)
sharedAddressesMap := make(map[string]struct{}, len(sharedAddresses))
for _, acc := range sharedAddresses {
sharedAddressesMap[acc.String()] = struct{}{}
}
s.Require().Len(sharedAddressesMap, 2)
s.Require().Contains(sharedAddressesMap, aliceAddress1)
s.Require().Contains(sharedAddressesMap, aliceAddress2)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestResendSharedAddressesOnBackupRestore() {
community, _ := createCommunity(&s.Suite, s.owner)
// bob joins the community
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
s.joinCommunity(community, s.bob, bobPassword, []string{bobAddress})
currentBobSharedAddresses, err := s.bob.GetRevealedAccounts(community.ID(), s.bob.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Len(currentBobSharedAddresses, 1)
requestID := communities.CalculateRequestID(s.bob.IdentityPublicKeyString(), community.ID())
err = s.bob.communitiesManager.RemoveRequestToJoinRevealedAddresses(requestID)
s.Require().NoError(err)
emptySharedAddresses, err := s.bob.GetRevealedAccounts(community.ID(), s.bob.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Len(emptySharedAddresses, 0)
// Simulate backup creation and handling backup message
// As a result, bob sends request to resend encryption keys to the owner
clock, _ := s.bob.getLastClockWithRelatedChat()
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
backupMessage, err := s.bob.backupCommunity(community, clock)
s.Require().NoError(err)
err = s.bob.HandleBackup(s.bob.buildMessageState(), backupMessage, nil)
s.Require().NoError(err)
// Owner will receive the request for addresses and send them back to Bob
response, err := WaitOnMessengerResponse(
s.bob,
func(r *MessengerResponse) bool {
_, _ = s.owner.RetrieveAll()
return len(r.requestsToJoinCommunity) > 0
},
"request to join not received",
)
s.Require().NoError(err)
requestToJoin, ok := response.requestsToJoinCommunity[requestID.String()]
s.Require().Equal(true, ok)
s.Require().Equal(currentBobSharedAddresses, requestToJoin.RevealedAccounts)
currentBobSharedAddresses, err = s.bob.GetRevealedAccounts(community.ID(), s.bob.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Len(currentBobSharedAddresses, 1)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterReceivesMembersSharedAddressesOnBackupRestore() {
community, _ := createCommunity(&s.Suite, s.owner)
tokenCriteria := createTokenMasterTokenCriteria()
_, err := s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{
CommunityID: community.ID(),
Type: protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER,
TokenCriteria: []*protobuf.TokenCriteria{tokenCriteria},
})
s.Require().NoError(err)
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
s.joinCommunity(community, s.alice, alicePassword, []string{aliceAddress1})
expectedAliceRevealedAccounts, err := s.alice.GetRevealedAccounts(community.ID(), s.alice.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Len(expectedAliceRevealedAccounts, 1)
s.Require().Equal(expectedAliceRevealedAccounts[0].Address, aliceAddress1)
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
// make bob satisfy the Token Master criteria
s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, tokenCriteria)
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
s.joinCommunity(community, s.bob, bobPassword, []string{bobAddress})
s.Require().NoError(err)
// check bob has TM role
community, err = s.bob.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
checkRoleBasedOnThePermissionType(protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER, &s.bob.identity.PublicKey, community)
s.waitForRevealedAddresses(s.bob, community.ID(), expectedAliceRevealedAccounts)
// remove alice revealed addresses
requestToDelete, err := s.bob.communitiesManager.GetRequestToJoinByPkAndCommunityID(s.alice.IdentityPublicKey(), community.ID())
s.Require().NoError(err)
err = s.bob.communitiesManager.RemoveRequestToJoinRevealedAddresses(requestToDelete.ID)
s.Require().NoError(err)
err = s.bob.communitiesManager.DeletePendingRequestToJoin(requestToDelete)
s.Require().NoError(err)
emptySharedAddresses, err := s.bob.GetRevealedAccounts(community.ID(), s.alice.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Len(emptySharedAddresses, 0)
s.Require().NotEqual(emptySharedAddresses, expectedAliceRevealedAccounts)
// Simulate backup creation and handling backup message
// As a result, bob sends request to resend encryption keys to the owner
clock, _ := s.bob.getLastClockWithRelatedChat()
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
backupMessage, err := s.bob.backupCommunity(community, clock)
s.Require().NoError(err)
err = s.bob.HandleBackup(s.bob.buildMessageState(), backupMessage, nil)
s.Require().NoError(err)
// Owner will receive the request for addresses and send requests to join with revealed
// addresses to token master
_, err = WaitOnMessengerResponse(
s.bob,
func(r *MessengerResponse) bool {
_, _ = s.owner.RetrieveAll()
aliceAccounts, err := s.bob.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString())
s.Require().NoError(err)
return len(aliceAccounts) > 0 && aliceAccounts[0].Address == aliceAddress1
},
"alice request to join with revealed addresses not received",
)
s.Require().NoError(err)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterReceivedRevealedAddressesFromJoinedMember() {
community, _ := createCommunity(&s.Suite, s.owner)
tokenCriteria := createTokenMasterTokenCriteria()
_, err := s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{
CommunityID: community.ID(),
Type: protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER,
TokenCriteria: []*protobuf.TokenCriteria{tokenCriteria},
})
s.Require().NoError(err)
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
s.Require().Len(community.TokenPermissions(), 1)
// make bob satisfy the Token Master criteria
s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, tokenCriteria)
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
s.joinCommunity(community, s.bob, bobPassword, []string{bobAddress})
// check bob has TM role
community, err = s.bob.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
checkRoleBasedOnThePermissionType(protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER, &s.bob.identity.PublicKey, community)
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
s.joinCommunity(community, s.alice, alicePassword, []string{aliceAddress1})
expectedAliceRevealedAccounts, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Len(expectedAliceRevealedAccounts, 1)
s.Require().Equal(expectedAliceRevealedAccounts[0].Address, aliceAddress1)
s.Require().Equal(true, expectedAliceRevealedAccounts[0].IsAirdropAddress)
// check that bob received revealed address
_, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool {
return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStateAccepted, len(expectedAliceRevealedAccounts))
}, "user not accepted")
s.Require().NoError(err)
s.checkRevealedAccounts(community.ID(), s.bob, expectedAliceRevealedAccounts)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterJoinedToCommunityAndReceivedRevealedAddresses() {
community, _ := createCommunity(&s.Suite, s.owner)
tokenCriteria := createTokenMasterTokenCriteria()
_, err := s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{
CommunityID: community.ID(),
Type: protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER,
TokenCriteria: []*protobuf.TokenCriteria{tokenCriteria},
})
s.Require().NoError(err)
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
s.Require().Len(community.TokenPermissions(), 1)
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
s.joinCommunity(community, s.alice, alicePassword, []string{aliceAddress1})
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
// make bob satisfy the Token Master criteria
s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, tokenCriteria)
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
s.joinCommunity(community, s.bob, bobPassword, []string{bobAddress})
community, err = s.bob.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
checkRoleBasedOnThePermissionType(protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER, &s.bob.identity.PublicKey, community)
expectedAliceRevealedAccounts, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Len(expectedAliceRevealedAccounts, 1)
s.Require().Equal(expectedAliceRevealedAccounts[0].Address, aliceAddress1)
s.Require().Equal(true, expectedAliceRevealedAccounts[0].IsAirdropAddress)
s.waitForRevealedAddresses(s.bob, community.ID(), expectedAliceRevealedAccounts)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestMemberReceivedSharedAddressOnGettingTokenMasterRole() {
community, _ := createCommunity(&s.Suite, s.owner)
community, err := s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
s.Require().Len(community.TokenPermissions(), 0)
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
s.joinCommunity(community, s.alice, alicePassword, []string{aliceAddress1})
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
s.joinCommunity(community, s.bob, bobPassword, []string{bobAddress})
tokenCriteria := createTokenMasterTokenCriteria()
// make bob satisfy the Token Master criteria
s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, tokenCriteria)
// wait for owner to send sync message for bob, who got a TM role
waitOnOwnerSendSyncMessage := waitOnCommunitiesEvent(s.owner, func(sub *communities.Subscription) bool {
return sub.CommunityPrivilegedMemberSyncMessage != nil &&
sub.CommunityPrivilegedMemberSyncMessage.CommunityPrivilegedUserSyncMessage.Type == protobuf.CommunityPrivilegedUserSyncMessage_CONTROL_NODE_ALL_SYNC_REQUESTS_TO_JOIN &&
len(sub.CommunityPrivilegedMemberSyncMessage.Receivers) == 1 &&
sub.CommunityPrivilegedMemberSyncMessage.Receivers[0].Equal(&s.bob.identity.PublicKey)
})
_, err = s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{
CommunityID: community.ID(),
Type: protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER,
TokenCriteria: []*protobuf.TokenCriteria{tokenCriteria},
})
s.Require().NoError(err)
err = <-waitOnOwnerSendSyncMessage
s.Require().NoError(err)
expectedAliceRevealedAccounts, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Len(expectedAliceRevealedAccounts, 1)
s.Require().Equal(expectedAliceRevealedAccounts[0].Address, aliceAddress1)
s.Require().Equal(true, expectedAliceRevealedAccounts[0].IsAirdropAddress)
_, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool {
return len(r.Communities()) == 1 && r.Communities()[0].IsTokenMaster()
}, "bob didn't receive token master role")
s.Require().NoError(err)
s.waitForRevealedAddresses(s.bob, community.ID(), expectedAliceRevealedAccounts)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterReceivesAccountsAfterPendingRequestToJoinApproval() {
community, _ := createOnRequestCommunity(&s.Suite, s.owner)
tokenCriteria := createTokenMasterTokenCriteria()
// make bob satisfy the Token Master criteria
s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, tokenCriteria)
_, err := s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{
CommunityID: community.ID(),
Type: protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER,
TokenCriteria: []*protobuf.TokenCriteria{tokenCriteria},
})
s.Require().NoError(err)
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
s.Require().Len(community.TokenPermissions(), 1)
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
aliceRequest := createRequestToJoinCommunity(&s.Suite, community.ID(), s.alice, alicePassword, []string{aliceAddress1})
aliceRequestToJoinID := requestToJoinCommunity(&s.Suite, s.owner, s.alice, aliceRequest)
s.joinOnRequestCommunityAsTokenMaster(community)
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
s.Require().True(community.IsMemberTokenMaster(&s.bob.identity.PublicKey))
_, err = s.owner.AcceptRequestToJoinCommunity(&requests.AcceptRequestToJoinCommunity{ID: aliceRequestToJoinID})
s.Require().NoError(err)
_, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool {
return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStateAccepted, 1)
}, "bob didn't receive accepted Alice request to join")
s.Require().NoError(err)
expectedAliceRevealedAccounts, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Len(expectedAliceRevealedAccounts, 1)
s.Require().Equal(expectedAliceRevealedAccounts[0].Address, aliceAddress1)
s.Require().Equal(true, expectedAliceRevealedAccounts[0].IsAirdropAddress)
s.checkRevealedAccounts(community.ID(), s.bob, expectedAliceRevealedAccounts)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestMemberReceivesPendingRequestToJoinAfterAfterGettingTokenMasterRole() {
community, _ := createOnRequestCommunity(&s.Suite, s.owner)
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
aliceRequest := createRequestToJoinCommunity(&s.Suite, community.ID(), s.alice, alicePassword, []string{aliceAddress1})
aliceRequestToJoinID := requestToJoinCommunity(&s.Suite, s.owner, s.alice, aliceRequest)
joinOnRequestCommunity(&s.Suite, community.ID(), s.owner, s.bob, bobPassword, []string{bobAddress})
tokenCriteria := createTokenMasterTokenCriteria()
// make bob satisfy the Token Master criteria
s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, tokenCriteria)
_, err := s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{
CommunityID: community.ID(),
Type: protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER,
TokenCriteria: []*protobuf.TokenCriteria{tokenCriteria},
})
s.Require().NoError(err)
_, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool {
return len(r.Communities()) == 1 && r.Communities()[0].IsTokenMaster()
}, "bob didn't receive token master role")
s.Require().NoError(err)
_, err = s.owner.AcceptRequestToJoinCommunity(&requests.AcceptRequestToJoinCommunity{ID: aliceRequestToJoinID})
s.Require().NoError(err)
_, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool {
return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStateAccepted, 1)
}, "bob didn't receive accepted Alice request to join")
s.Require().NoError(err)
expectedAliceRevealedAccounts, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Len(expectedAliceRevealedAccounts, 1)
s.Require().Equal(expectedAliceRevealedAccounts[0].Address, aliceAddress1)
s.Require().Equal(true, expectedAliceRevealedAccounts[0].IsAirdropAddress)
s.checkRevealedAccounts(community.ID(), s.bob, expectedAliceRevealedAccounts)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestHandlingOutdatedPrivilegedUserSyncMessages() {
community, _ := createCommunity(&s.Suite, s.owner)
tokenCriteria := createTokenMasterTokenCriteria()
_, err := s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{
CommunityID: community.ID(),
Type: protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER,
TokenCriteria: []*protobuf.TokenCriteria{tokenCriteria},
})
s.Require().NoError(err)
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
s.Require().Len(community.TokenPermissions(), 1)
// make bob satisfy the Token Master criteria
s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, tokenCriteria)
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
s.joinCommunity(community, s.bob, bobPassword, []string{bobAddress})
// check bob has TM role
community, err = s.bob.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
checkRoleBasedOnThePermissionType(protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER, &s.bob.identity.PublicKey, community)
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
s.joinCommunity(community, s.alice, alicePassword, []string{aliceAddress1})
// check that bob received revealed address
_, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool {
return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStateAccepted, 1)
}, "bob did not receive alice revealed addresses")
s.Require().NoError(err)
// handle outdated CommunityPrivilegedUserSyncMessage_CONTROL_NODE_ALL_SYNC_REQUESTS_TO_JOIN msg
expectedAliceRequestToJoin, err := s.bob.communitiesManager.GetRequestToJoinByPkAndCommunityID(s.alice.IdentityPublicKey(), community.ID())
s.Require().NoError(err)
s.Require().NotNil(expectedAliceRequestToJoin)
bobRequestToJoin, err := s.bob.communitiesManager.GetRequestToJoinByPkAndCommunityID(s.bob.IdentityPublicKey(), community.ID())
s.Require().NoError(err)
s.Require().NotNil(bobRequestToJoin)
invalidAliceSyncRtj := expectedAliceRequestToJoin.ToSyncProtobuf()
invalidAliceSyncRtj.RevealedAccounts = bobRequestToJoin.RevealedAccounts
invalidAliceSyncRtj.EnsName = "corrupted"
invalidAliceSyncRtj.State = uint64(communities.RequestToJoinStatePending)
syncMsg := &protobuf.CommunityPrivilegedUserSyncMessage{
Type: protobuf.CommunityPrivilegedUserSyncMessage_CONTROL_NODE_ALL_SYNC_REQUESTS_TO_JOIN,
CommunityId: community.ID(),
SyncRequestsToJoin: []*protobuf.SyncCommunityRequestsToJoin{invalidAliceSyncRtj},
}
state := &ReceivedMessageState{
CurrentMessageState: &CurrentMessageState{
PublicKey: community.PublicKey(),
},
}
err = s.bob.HandleCommunityPrivilegedUserSyncMessage(state, syncMsg, nil)
s.Require().NoError(err)
aliceRtj, err := s.bob.communitiesManager.GetRequestToJoinByPkAndCommunityID(s.alice.IdentityPublicKey(), community.ID())
s.Require().NoError(err)
s.Require().Equal(aliceRtj, expectedAliceRequestToJoin)
// handle outdated CommunityPrivilegedUserSyncMessage_CONTROL_NODE_ACCEPT_REQUEST_TO_JOIN msg
invalidAliceCommunityRtj := aliceRtj.ToCommunityRequestToJoinProtobuf()
invalidAliceCommunityRtj.RevealedAccounts = bobRequestToJoin.RevealedAccounts
invalidAliceCommunityRtj.EnsName = "corrupted"
syncMsg.Type = protobuf.CommunityPrivilegedUserSyncMessage_CONTROL_NODE_ACCEPT_REQUEST_TO_JOIN
syncMsg.RequestToJoin = map[string]*protobuf.CommunityRequestToJoin{
s.alice.IdentityPublicKeyString(): invalidAliceCommunityRtj,
}
err = s.bob.HandleCommunityPrivilegedUserSyncMessage(state, syncMsg, nil)
s.Require().NoError(err)
aliceRtj, err = s.bob.communitiesManager.GetRequestToJoinByPkAndCommunityID(s.alice.IdentityPublicKey(), community.ID())
s.Require().NoError(err)
s.Require().Equal(aliceRtj, expectedAliceRequestToJoin)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestMemberReceivedEditedSharedAddressOnGettingTokenMasterRole() {
community, _ := createCommunity(&s.Suite, s.owner)
alicePubkey := s.alice.IdentityPublicKeyString()
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
s.joinCommunity(community, s.alice, alicePassword, []string{aliceAddress1})
request := s.createEditSharedAddressesRequest(community.ID())
response, err := s.alice.EditSharedAddressesForCommunity(request)
s.Require().NoError(err)
s.Require().NotNil(response)
expectedAliceRevealedAccounts, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), alicePubkey)
s.Require().NoError(err)
s.Require().Len(expectedAliceRevealedAccounts, 1)
s.Require().Equal(expectedAliceRevealedAccounts[0].Address, aliceAddress2)
s.Require().Equal(true, expectedAliceRevealedAccounts[0].IsAirdropAddress)
// check that owner received edited shared adresses
s.waitForRevealedAddresses(s.owner, community.ID(), expectedAliceRevealedAccounts)
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
s.joinCommunity(community, s.bob, bobPassword, []string{bobAddress})
tokenCriteria := createTokenMasterTokenCriteria()
// make bob satisfy the Token Master criteria
s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, tokenCriteria)
_, err = s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{
CommunityID: community.ID(),
Type: protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER,
TokenCriteria: []*protobuf.TokenCriteria{tokenCriteria},
})
s.Require().NoError(err)
_, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool {
return len(r.Communities()) == 1 && r.Communities()[0].IsTokenMaster()
}, "bob didn't receive token master role")
s.Require().NoError(err)
s.waitForRevealedAddresses(s.bob, community.ID(), expectedAliceRevealedAccounts)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestMemberReceivesAccountsOnRoleChangeFromAdminToTokenMaster() {
community, _ := createCommunity(&s.Suite, s.owner)
alicePublicKey := s.alice.IdentityPublicKeyString()
adminTokenCriteria := &protobuf.TokenCriteria{
ContractAddresses: map[uint64]string{testChainID1: "0x125"},
Type: protobuf.CommunityTokenType_ERC20,
Symbol: "STT",
Name: "Status Test Token",
AmountInWei: "10000000000000000000",
Decimals: 18,
}
tokenMasterTokenCriteria := createTokenMasterTokenCriteria()
_, err := s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{
CommunityID: community.ID(),
Type: protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER,
TokenCriteria: []*protobuf.TokenCriteria{tokenMasterTokenCriteria},
})
s.Require().NoError(err)
_, err = s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{
CommunityID: community.ID(),
Type: protobuf.CommunityTokenPermission_BECOME_ADMIN,
TokenCriteria: []*protobuf.TokenCriteria{adminTokenCriteria},
})
s.Require().NoError(err)
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
s.Require().Len(community.TokenPermissions(), 2)
// make bob satisfy the admin criteria
s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, adminTokenCriteria)
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
s.joinCommunity(community, s.bob, bobPassword, []string{bobAddress})
// check bob has admin role
community, err = s.bob.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
checkRoleBasedOnThePermissionType(protobuf.CommunityTokenPermission_BECOME_ADMIN, &s.bob.identity.PublicKey, community)
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
s.joinCommunity(community, s.alice, alicePassword, []string{aliceAddress1})
expectedAliceRevealedAccounts, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), alicePublicKey)
s.Require().NoError(err)
s.Require().Len(expectedAliceRevealedAccounts, 1)
s.Require().Equal(expectedAliceRevealedAccounts[0].Address, aliceAddress1)
s.Require().Equal(true, expectedAliceRevealedAccounts[0].IsAirdropAddress)
// check that bob received alice request to join without revealed accounts
_, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool {
return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStateAccepted, 0)
}, "alice request to join was not delivered to admin bob")
s.Require().NoError(err)
emptyAliceAccounts, err := s.bob.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Len(emptyAliceAccounts, 0)
// make bob satisfy TokenMaster criteria
s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, tokenMasterTokenCriteria)
// wait for owner to send sync message for bob, who got a TM role
waitOnOwnerSendSyncMessage := waitOnCommunitiesEvent(s.owner, func(sub *communities.Subscription) bool {
return sub.CommunityPrivilegedMemberSyncMessage != nil &&
sub.CommunityPrivilegedMemberSyncMessage.CommunityPrivilegedUserSyncMessage.Type == protobuf.CommunityPrivilegedUserSyncMessage_CONTROL_NODE_ALL_SYNC_REQUESTS_TO_JOIN &&
len(sub.CommunityPrivilegedMemberSyncMessage.Receivers) == 1 &&
sub.CommunityPrivilegedMemberSyncMessage.Receivers[0].Equal(&s.bob.identity.PublicKey)
})
err = s.owner.communitiesManager.ForceMembersReevaluation(community.ID())
s.Require().NoError(err)
err = <-waitOnOwnerSendSyncMessage
s.Require().NoError(err)
// check that bob received alice request to join with revealed accounts
s.waitForRevealedAddresses(s.bob, community.ID(), expectedAliceRevealedAccounts)
}
func (s *MessengerCommunitiesSharedMemberAddressSuite) TestOwnerRejectAndAcceptAliceRequestToJoin() {
community, _ := createOnRequestCommunity(&s.Suite, s.owner)
s.Require().False(community.AutoAccept())
tokenCriteria := createTokenMasterTokenCriteria()
// make bob satisfy the Token Master criteria
s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, tokenCriteria)
_, err := s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{
CommunityID: community.ID(),
Type: protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER,
TokenCriteria: []*protobuf.TokenCriteria{tokenCriteria},
})
s.Require().NoError(err)
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
s.Require().Len(community.TokenPermissions(), 1)
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
s.joinOnRequestCommunityAsTokenMaster(community)
community, err = s.owner.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
s.Require().True(community.IsMemberTokenMaster(&s.bob.identity.PublicKey))
advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
aliceRequest := createRequestToJoinCommunity(&s.Suite, community.ID(), s.alice, alicePassword, []string{aliceAddress1})
aliceRequestToJoinID := requestToJoinCommunity(&s.Suite, s.owner, s.alice, aliceRequest)
// check that bob received alice request to join without revealed accounts due to pending state
_, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool {
return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStatePending, 0)
}, "alice pending request to join was not delivered to token master bob")
s.Require().NoError(err)
// request to join was not approved, bob should not have alice revealed addresses
aliceRevealedAccounts, err := s.bob.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Len(aliceRevealedAccounts, 0)
_, err = s.owner.DeclineRequestToJoinCommunity(&requests.DeclineRequestToJoinCommunity{ID: aliceRequestToJoinID})
s.Require().NoError(err)
// check that bob received owner decline sync msg
_, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool {
return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStateDeclined, 0)
}, "alice declined request to join was not delivered to token master bob")
s.Require().NoError(err)
// request to join was declined, bob should not have alice revealed addresses
aliceRevealedAccounts, err = s.bob.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Len(aliceRevealedAccounts, 0)
_, err = s.owner.AcceptRequestToJoinCommunity(&requests.AcceptRequestToJoinCommunity{ID: aliceRequestToJoinID})
s.Require().NoError(err)
_, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool {
return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStateAccepted, len(aliceRequest.AddressesToReveal))
}, "bob didn't receive accepted Alice request to join")
s.Require().NoError(err)
// request to join was accepted, bob should have alice revealed addresses
aliceRevealedAccounts, err = s.bob.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString())
s.Require().NoError(err)
s.Require().Len(aliceRevealedAccounts, 1)
}