mirror of
https://github.com/Qortal/qortal.git
synced 2025-04-14 23:35:54 +00:00
supporting multiple minting groups instead of supporting one and only one minting group
This commit is contained in:
parent
9017db725e
commit
91ceafe0e3
@ -14,6 +14,7 @@ import org.qortal.repository.NameRepository;
|
||||
import org.qortal.repository.Repository;
|
||||
import org.qortal.settings.Settings;
|
||||
import org.qortal.utils.Base58;
|
||||
import org.qortal.utils.Groups;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
@ -227,7 +228,7 @@ public class Account {
|
||||
}
|
||||
|
||||
int level = accountData.getLevel();
|
||||
int groupIdToMint = BlockChain.getInstance().getMintingGroupId();
|
||||
List<Integer> groupIdsToMint = Groups.getGroupIdsToMint( BlockChain.getInstance(), blockchainHeight );
|
||||
int nameCheckHeight = BlockChain.getInstance().getOnlyMintWithNameHeight();
|
||||
int groupCheckHeight = BlockChain.getInstance().getGroupMemberCheckHeight();
|
||||
int removeNameCheckHeight = BlockChain.getInstance().getRemoveOnlyMintWithNameHeight();
|
||||
@ -261,9 +262,9 @@ public class Account {
|
||||
if (blockchainHeight >= groupCheckHeight && blockchainHeight < removeNameCheckHeight) {
|
||||
List<NameData> myName = nameRepository.getNamesByOwner(myAddress);
|
||||
if (Account.isFounder(accountData.getFlags())) {
|
||||
return accountData.getBlocksMintedPenalty() == 0 && !myName.isEmpty() && (isGroupValidated || groupRepository.memberExists(groupIdToMint, myAddress));
|
||||
return accountData.getBlocksMintedPenalty() == 0 && !myName.isEmpty() && (isGroupValidated || Groups.memberExistsInAnyGroup(groupRepository, groupIdsToMint, myAddress));
|
||||
} else {
|
||||
return level >= levelToMint && !myName.isEmpty() && (isGroupValidated || groupRepository.memberExists(groupIdToMint, myAddress));
|
||||
return level >= levelToMint && !myName.isEmpty() && (isGroupValidated || Groups.memberExistsInAnyGroup(groupRepository, groupIdsToMint, myAddress));
|
||||
}
|
||||
}
|
||||
|
||||
@ -272,9 +273,9 @@ public class Account {
|
||||
// Account's address is a member of the minter group
|
||||
if (blockchainHeight >= removeNameCheckHeight) {
|
||||
if (Account.isFounder(accountData.getFlags())) {
|
||||
return accountData.getBlocksMintedPenalty() == 0 && (isGroupValidated || groupRepository.memberExists(groupIdToMint, myAddress));
|
||||
return accountData.getBlocksMintedPenalty() == 0 && (isGroupValidated || Groups.memberExistsInAnyGroup(groupRepository, groupIdsToMint, myAddress));
|
||||
} else {
|
||||
return level >= levelToMint && (isGroupValidated || groupRepository.memberExists(groupIdToMint, myAddress));
|
||||
return level >= levelToMint && (isGroupValidated || Groups.memberExistsInAnyGroup(groupRepository, groupIdsToMint, myAddress));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ import org.qortal.transform.block.BlockTransformer;
|
||||
import org.qortal.transform.transaction.TransactionTransformer;
|
||||
import org.qortal.utils.Amounts;
|
||||
import org.qortal.utils.Base58;
|
||||
import org.qortal.utils.Groups;
|
||||
import org.qortal.utils.NTP;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@ -150,7 +151,7 @@ public class Block {
|
||||
|
||||
final BlockChain blockChain = BlockChain.getInstance();
|
||||
|
||||
ExpandedAccount(Repository repository, RewardShareData rewardShareData) throws DataException {
|
||||
ExpandedAccount(Repository repository, RewardShareData rewardShareData, int blockHeight) throws DataException {
|
||||
this.rewardShareData = rewardShareData;
|
||||
this.sharePercent = this.rewardShareData.getSharePercent();
|
||||
|
||||
@ -159,7 +160,12 @@ public class Block {
|
||||
this.isMinterFounder = Account.isFounder(mintingAccountData.getFlags());
|
||||
|
||||
this.isRecipientAlsoMinter = this.rewardShareData.getRecipient().equals(this.mintingAccount.getAddress());
|
||||
this.isMinterMember = repository.getGroupRepository().memberExists(BlockChain.getInstance().getMintingGroupId(), this.mintingAccount.getAddress());
|
||||
this.isMinterMember
|
||||
= Groups.memberExistsInAnyGroup(
|
||||
repository.getGroupRepository(),
|
||||
Groups.getGroupIdsToMint(BlockChain.getInstance(), blockHeight),
|
||||
this.mintingAccount.getAddress()
|
||||
);
|
||||
|
||||
if (this.isRecipientAlsoMinter) {
|
||||
// Self-share: minter is also recipient
|
||||
@ -435,9 +441,9 @@ public class Block {
|
||||
if (height >= BlockChain.getInstance().getGroupMemberCheckHeight()) {
|
||||
onlineAccounts.removeIf(a -> {
|
||||
try {
|
||||
int groupId = BlockChain.getInstance().getMintingGroupId();
|
||||
List<Integer> groupIdsToMint = Groups.getGroupIdsToMint(BlockChain.getInstance(), height);
|
||||
String address = Account.getRewardShareMintingAddress(repository, a.getPublicKey());
|
||||
boolean isMinterGroupMember = repository.getGroupRepository().memberExists(groupId, address);
|
||||
boolean isMinterGroupMember = Groups.memberExistsInAnyGroup(repository.getGroupRepository(), groupIdsToMint, address);
|
||||
return !isMinterGroupMember;
|
||||
} catch (DataException e) {
|
||||
// Something went wrong, so remove the account
|
||||
@ -753,7 +759,7 @@ public class Block {
|
||||
List<ExpandedAccount> expandedAccounts = new ArrayList<>();
|
||||
|
||||
for (RewardShareData rewardShare : this.cachedOnlineRewardShares) {
|
||||
expandedAccounts.add(new ExpandedAccount(repository, rewardShare));
|
||||
expandedAccounts.add(new ExpandedAccount(repository, rewardShare, this.blockData.getHeight()));
|
||||
}
|
||||
|
||||
this.cachedExpandedAccounts = expandedAccounts;
|
||||
@ -2485,11 +2491,10 @@ public class Block {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
GroupRepository groupRepository = repository.getGroupRepository();
|
||||
|
||||
List<Integer> mintingGroupIds = Groups.getGroupIdsToMint(BlockChain.getInstance(), this.blockData.getHeight());
|
||||
|
||||
// all minter admins
|
||||
List<String> minterAdmins
|
||||
= groupRepository.getGroupAdmins(BlockChain.getInstance().getMintingGroupId()).stream()
|
||||
.map(GroupAdminData::getAdmin)
|
||||
.collect(Collectors.toList());
|
||||
List<String> minterAdmins = Groups.getAllAdmins(groupRepository, mintingGroupIds);
|
||||
|
||||
// all minter admins that are online
|
||||
List<ExpandedAccount> onlineMinterAdminAccounts
|
||||
|
@ -212,7 +212,13 @@ public class BlockChain {
|
||||
private int minAccountLevelToRewardShare;
|
||||
private int maxRewardSharesPerFounderMintingAccount;
|
||||
private int founderEffectiveMintingLevel;
|
||||
private int mintingGroupId;
|
||||
|
||||
public static class IdsForHeight {
|
||||
public int height;
|
||||
public List<Integer> ids;
|
||||
}
|
||||
|
||||
private List<IdsForHeight> mintingGroupIds;
|
||||
|
||||
/** Minimum time to retain online account signatures (ms) for block validity checks. */
|
||||
private long onlineAccountSignaturesMinLifetime;
|
||||
@ -544,8 +550,8 @@ public class BlockChain {
|
||||
return this.onlineAccountSignaturesMaxLifetime;
|
||||
}
|
||||
|
||||
public int getMintingGroupId() {
|
||||
return this.mintingGroupId;
|
||||
public List<IdsForHeight> getMintingGroupIds() {
|
||||
return mintingGroupIds;
|
||||
}
|
||||
|
||||
public CiyamAtSettings getCiyamAtSettings() {
|
||||
|
@ -25,6 +25,7 @@ import org.qortal.repository.Repository;
|
||||
import org.qortal.repository.RepositoryManager;
|
||||
import org.qortal.settings.Settings;
|
||||
import org.qortal.utils.Base58;
|
||||
import org.qortal.utils.Groups;
|
||||
import org.qortal.utils.NTP;
|
||||
import org.qortal.utils.NamedThreadFactory;
|
||||
|
||||
@ -225,11 +226,14 @@ public class OnlineAccountsManager {
|
||||
Set<OnlineAccountData> onlineAccountsToAdd = new HashSet<>();
|
||||
Set<OnlineAccountData> onlineAccountsToRemove = new HashSet<>();
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
|
||||
int blockHeight = repository.getBlockRepository().getBlockchainHeight();
|
||||
|
||||
List<String> mintingGroupMemberAddresses
|
||||
= repository.getGroupRepository()
|
||||
.getGroupMembers(BlockChain.getInstance().getMintingGroupId()).stream()
|
||||
.map(GroupMemberData::getMember)
|
||||
.collect(Collectors.toList());
|
||||
= Groups.getAllMembers(
|
||||
repository.getGroupRepository(),
|
||||
Groups.getGroupIdsToMint(BlockChain.getInstance(), blockHeight)
|
||||
);
|
||||
|
||||
for (OnlineAccountData onlineAccountData : this.onlineAccountsImportQueue) {
|
||||
if (isStopping)
|
||||
|
@ -53,10 +53,10 @@ public class Blocks {
|
||||
|
||||
// all minting group member addresses
|
||||
List<String> mintingGroupAddresses
|
||||
= repository.getGroupRepository()
|
||||
.getGroupMembers(BlockChain.getInstance().getMintingGroupId()).stream()
|
||||
.map(GroupMemberData::getMember)
|
||||
.collect(Collectors.toList());
|
||||
= Groups.getAllMembers(
|
||||
repository.getGroupRepository(),
|
||||
Groups.getGroupIdsToMint(BlockChain.getInstance(), blockData.getHeight())
|
||||
);
|
||||
|
||||
// all names, indexed by address
|
||||
Map<String, String> nameByAddress
|
||||
|
122
src/main/java/org/qortal/utils/Groups.java
Normal file
122
src/main/java/org/qortal/utils/Groups.java
Normal file
@ -0,0 +1,122 @@
|
||||
package org.qortal.utils;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.group.GroupAdminData;
|
||||
import org.qortal.data.group.GroupMemberData;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.GroupRepository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Class Groups
|
||||
*
|
||||
* A utility class for group related functionality.
|
||||
*/
|
||||
public class Groups {
|
||||
|
||||
/**
|
||||
* Does the member exist in any of these groups?
|
||||
*
|
||||
* @param groupRepository the group data repository
|
||||
* @param groupsIds the group Ids to look for the address
|
||||
* @param address the address
|
||||
*
|
||||
* @return true if the address is in any of the groups listed otherwise false
|
||||
* @throws DataException
|
||||
*/
|
||||
public static boolean memberExistsInAnyGroup(GroupRepository groupRepository, List<Integer> groupsIds, String address) throws DataException {
|
||||
|
||||
// if any of the listed groups have the address as a member, then return true
|
||||
for( Integer groupIdToMint : groupsIds) {
|
||||
if( groupRepository.memberExists(groupIdToMint, address) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// if none of the listed groups have the address as a member, then return false
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get All Members
|
||||
*
|
||||
* Get all the group members from a list of groups.
|
||||
*
|
||||
* @param groupRepository the group data repository
|
||||
* @param groupIds the list of group Ids to look at
|
||||
*
|
||||
* @return the list of all members belonging to any of the groups, no duplicates
|
||||
* @throws DataException
|
||||
*/
|
||||
public static List<String> getAllMembers( GroupRepository groupRepository, List<Integer> groupIds ) throws DataException {
|
||||
// collect all the members in a set, the set keeps out duplicates
|
||||
Set<String> allMembers = new HashSet<>();
|
||||
|
||||
// add all members from each group to the all members set
|
||||
for( int groupId : groupIds ) {
|
||||
allMembers.addAll( groupRepository.getGroupMembers(groupId).stream().map(GroupMemberData::getMember).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
return new ArrayList<>(allMembers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get All Admins
|
||||
*
|
||||
* Get all the admins from a list of groups.
|
||||
*
|
||||
* @param groupRepository the group data repository
|
||||
* @param groupIds the list of group Ids to look at
|
||||
*
|
||||
* @return the list of all admins to any of the groups, no duplicates
|
||||
* @throws DataException
|
||||
*/
|
||||
public static List<String> getAllAdmins( GroupRepository groupRepository, List<Integer> groupIds ) throws DataException {
|
||||
// collect all the admins in a set, the set keeps out duplicates
|
||||
Set<String> allAdmins = new HashSet<>();
|
||||
|
||||
// collect admins for each group
|
||||
for( int groupId : groupIds ) {
|
||||
allAdmins.addAll( groupRepository.getGroupAdmins(groupId).stream().map(GroupAdminData::getAdmin).collect(Collectors.toList()) );
|
||||
}
|
||||
|
||||
return new ArrayList<>(allAdmins);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Group Ids To Mint
|
||||
*
|
||||
* @param blockchain the blockchain
|
||||
* @param blockchainHeight the block height to mint
|
||||
*
|
||||
* @return the group Ids for the minting groups at the height given
|
||||
*/
|
||||
public static List<Integer> getGroupIdsToMint(BlockChain blockchain, int blockchainHeight) {
|
||||
|
||||
// sort heights lowest to highest
|
||||
Comparator<BlockChain.IdsForHeight> compareByHeight = Comparator.comparingInt(entry -> entry.height);
|
||||
|
||||
// sort heights highest to lowest
|
||||
Comparator<BlockChain.IdsForHeight> compareByHeightReversed = compareByHeight.reversed();
|
||||
|
||||
// get highest height that is less than the blockchain height
|
||||
Optional<BlockChain.IdsForHeight> ids = blockchain.getMintingGroupIds().stream()
|
||||
.filter(entry -> entry.height < blockchainHeight)
|
||||
.sorted(compareByHeightReversed)
|
||||
.findFirst();
|
||||
|
||||
if( ids.isPresent()) {
|
||||
return ids.get().ids;
|
||||
}
|
||||
else {
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
}
|
||||
}
|
@ -38,7 +38,9 @@
|
||||
"blockRewardBatchStartHeight": 1508000,
|
||||
"blockRewardBatchSize": 1000,
|
||||
"blockRewardBatchAccountsBlockCount": 25,
|
||||
"mintingGroupId": 694,
|
||||
"mintingGroupIds": [
|
||||
{ "height": 0, "ids": [ 694 ]}
|
||||
],
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 5.00 },
|
||||
{ "height": 259201, "reward": 4.75 },
|
||||
|
102
src/test/java/org/qortal/test/utils/GroupsTestUtils.java
Normal file
102
src/test/java/org/qortal/test/utils/GroupsTestUtils.java
Normal file
@ -0,0 +1,102 @@
|
||||
package org.qortal.test.utils;
|
||||
|
||||
import org.qortal.account.PrivateKeyAccount;
|
||||
import org.qortal.data.transaction.CreateGroupTransactionData;
|
||||
import org.qortal.data.transaction.GroupInviteTransactionData;
|
||||
import org.qortal.data.transaction.JoinGroupTransactionData;
|
||||
import org.qortal.data.transaction.LeaveGroupTransactionData;
|
||||
import org.qortal.group.Group;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
import org.qortal.test.common.TransactionUtils;
|
||||
import org.qortal.test.common.transaction.TestTransaction;
|
||||
|
||||
/**
|
||||
* Class GroupsTestUtils
|
||||
*
|
||||
* Utility methods for testing the Groups class.
|
||||
*/
|
||||
public class GroupsTestUtils {
|
||||
|
||||
/**
|
||||
* Create Group
|
||||
*
|
||||
* @param repository the data repository
|
||||
* @param owner the group owner
|
||||
* @param groupName the group name
|
||||
* @param isOpen true if the group is public, false for private
|
||||
*
|
||||
* @return the group Id
|
||||
* @throws DataException
|
||||
*/
|
||||
public static Integer createGroup(Repository repository, PrivateKeyAccount owner, String groupName, boolean isOpen) throws DataException {
|
||||
String description = groupName + " (description)";
|
||||
|
||||
Group.ApprovalThreshold approvalThreshold = Group.ApprovalThreshold.ONE;
|
||||
int minimumBlockDelay = 10;
|
||||
int maximumBlockDelay = 1440;
|
||||
|
||||
CreateGroupTransactionData transactionData = new CreateGroupTransactionData(TestTransaction.generateBase(owner), groupName, description, isOpen, approvalThreshold, minimumBlockDelay, maximumBlockDelay);
|
||||
TransactionUtils.signAndMint(repository, transactionData, owner);
|
||||
|
||||
return repository.getGroupRepository().fromGroupName(groupName).getGroupId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Join Group
|
||||
*
|
||||
* @param repository the data repository
|
||||
* @param joiner the address for the account joining the group
|
||||
* @param groupId the Id for the group to join
|
||||
*
|
||||
* @throws DataException
|
||||
*/
|
||||
public static void joinGroup(Repository repository, PrivateKeyAccount joiner, int groupId) throws DataException {
|
||||
JoinGroupTransactionData transactionData = new JoinGroupTransactionData(TestTransaction.generateBase(joiner), groupId);
|
||||
TransactionUtils.signAndMint(repository, transactionData, joiner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Group Invite
|
||||
*
|
||||
* @param repository the data repository
|
||||
* @param admin the admin account to sign the invite
|
||||
* @param groupId the Id of the group to invite to
|
||||
* @param invitee the recipient address for the invite
|
||||
* @param timeToLive the time length of the invite
|
||||
*
|
||||
* @throws DataException
|
||||
*/
|
||||
public static void groupInvite(Repository repository, PrivateKeyAccount admin, int groupId, String invitee, int timeToLive) throws DataException {
|
||||
GroupInviteTransactionData transactionData = new GroupInviteTransactionData(TestTransaction.generateBase(admin), groupId, invitee, timeToLive);
|
||||
TransactionUtils.signAndMint(repository, transactionData, admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Leave Group
|
||||
*
|
||||
* @param repository the data repository
|
||||
* @param leaver the account leaving
|
||||
* @param groupId the Id of the group being left
|
||||
*
|
||||
* @throws DataException
|
||||
*/
|
||||
public static void leaveGroup(Repository repository, PrivateKeyAccount leaver, int groupId) throws DataException {
|
||||
LeaveGroupTransactionData transactionData = new LeaveGroupTransactionData(TestTransaction.generateBase(leaver), groupId);
|
||||
TransactionUtils.signAndMint(repository, transactionData, leaver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is Member?
|
||||
*
|
||||
* @param repository the data repository
|
||||
* @param address the account address
|
||||
* @param groupId the group Id
|
||||
*
|
||||
* @return true if the account is a member of the group, otherwise false
|
||||
* @throws DataException
|
||||
*/
|
||||
public static boolean isMember(Repository repository, String address, int groupId) throws DataException {
|
||||
return repository.getGroupRepository().memberExists(groupId, address);
|
||||
}
|
||||
}
|
199
src/test/java/org/qortal/test/utils/GroupsTests.java
Normal file
199
src/test/java/org/qortal/test/utils/GroupsTests.java
Normal file
@ -0,0 +1,199 @@
|
||||
package org.qortal.test.utils;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.qortal.account.PrivateKeyAccount;
|
||||
import org.qortal.block.Block;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
import org.qortal.repository.RepositoryManager;
|
||||
import org.qortal.test.common.BlockUtils;
|
||||
import org.qortal.test.common.Common;
|
||||
import org.qortal.utils.Groups;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class GroupsTests extends Common {
|
||||
|
||||
public static final String ALICE = "alice";
|
||||
public static final String BOB = "bob";
|
||||
public static final String CHLOE = "chloe";
|
||||
public static final String DILBERT = "dilbert";
|
||||
|
||||
|
||||
private static final int HEIGHT_1 = 5;
|
||||
private static final int HEIGHT_2 = 8;
|
||||
private static final int HEIGHT_3 = 12;
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws DataException {
|
||||
Common.useDefaultSettings();
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterTest() throws DataException {
|
||||
Common.orphanCheck();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetGroupIdsToMintSimple() {
|
||||
List<Integer> ids = Groups.getGroupIdsToMint(BlockChain.getInstance(), 0);
|
||||
|
||||
Assert.assertNotNull(ids);
|
||||
Assert.assertEquals(0, ids.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetGroupIdsToMintComplex() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
|
||||
Block block1 = BlockUtils.mintBlocks(repository, HEIGHT_1);
|
||||
int height1 = block1.getBlockData().getHeight().intValue();
|
||||
assertEquals(HEIGHT_1 + 1, height1);
|
||||
|
||||
List<Integer> ids1 = Groups.getGroupIdsToMint(BlockChain.getInstance(), height1);
|
||||
|
||||
Assert.assertEquals(1, ids1.size() );
|
||||
Assert.assertTrue( ids1.contains( 694 ) );
|
||||
|
||||
Block block2 = BlockUtils.mintBlocks(repository, HEIGHT_2 - HEIGHT_1);
|
||||
int height2 = block2.getBlockData().getHeight().intValue();
|
||||
assertEquals( HEIGHT_2 + 1, height2);
|
||||
|
||||
List<Integer> ids2 = Groups.getGroupIdsToMint(BlockChain.getInstance(), height2);
|
||||
|
||||
Assert.assertEquals(2, ids2.size() );
|
||||
|
||||
Assert.assertTrue( ids2.contains( 694 ) );
|
||||
Assert.assertTrue( ids2.contains( 800 ) );
|
||||
|
||||
Block block3 = BlockUtils.mintBlocks(repository, HEIGHT_3 - HEIGHT_2);
|
||||
int height3 = block3.getBlockData().getHeight().intValue();
|
||||
assertEquals( HEIGHT_3 + 1, height3);
|
||||
|
||||
List<Integer> ids3 = Groups.getGroupIdsToMint(BlockChain.getInstance(), height3);
|
||||
|
||||
Assert.assertEquals( 1, ids3.size() );
|
||||
|
||||
Assert.assertTrue( ids3.contains( 800 ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMemberExistsInAnyGroupSimple() throws DataException {
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
PrivateKeyAccount bob = Common.getTestAccount(repository, "bob");
|
||||
|
||||
// Create group
|
||||
int groupId = GroupsTestUtils.createGroup(repository, alice, "closed-group", false);
|
||||
|
||||
// Confirm Bob is not a member
|
||||
Assert.assertFalse( Groups.memberExistsInAnyGroup(repository.getGroupRepository(), List.of(groupId), bob.getAddress()) );
|
||||
|
||||
// Bob to join
|
||||
GroupsTestUtils.joinGroup(repository, bob, groupId);
|
||||
|
||||
// Confirm Bob still not a member
|
||||
assertFalse(GroupsTestUtils.isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Have Alice 'invite' Bob to confirm membership
|
||||
GroupsTestUtils.groupInvite(repository, alice, groupId, bob.getAddress(), 0); // non-expiring invite
|
||||
|
||||
// Confirm Bob now a member
|
||||
Assert.assertTrue( Groups.memberExistsInAnyGroup(repository.getGroupRepository(), List.of(groupId), bob.getAddress()) );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupsListedFunctionality() throws DataException {
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, ALICE);
|
||||
PrivateKeyAccount bob = Common.getTestAccount(repository, BOB);
|
||||
PrivateKeyAccount chloe = Common.getTestAccount(repository, CHLOE);
|
||||
PrivateKeyAccount dilbert = Common.getTestAccount(repository, DILBERT);
|
||||
|
||||
// Create groups
|
||||
int group1Id = GroupsTestUtils.createGroup(repository, alice, "group-1", false);
|
||||
int group2Id = GroupsTestUtils.createGroup(repository, bob, "group-2", false);
|
||||
|
||||
// test memberExistsInAnyGroup
|
||||
Assert.assertTrue(Groups.memberExistsInAnyGroup(repository.getGroupRepository(), List.of(group1Id, group2Id), alice.getAddress()));
|
||||
Assert.assertFalse(Groups.memberExistsInAnyGroup(repository.getGroupRepository(), List.of(group1Id, group2Id), chloe.getAddress()));
|
||||
|
||||
// alice is a member
|
||||
Assert.assertTrue(GroupsTestUtils.isMember(repository, alice.getAddress(), group1Id));
|
||||
List<String> allMembersBeforeJoin = Groups.getAllMembers(repository.getGroupRepository(), List.of(group1Id));
|
||||
|
||||
// assert one member
|
||||
Assert.assertNotNull(allMembersBeforeJoin);
|
||||
Assert.assertEquals(1, allMembersBeforeJoin.size());
|
||||
|
||||
List<String> allAdminsBeforeJoin = Groups.getAllAdmins(repository.getGroupRepository(), List.of(group1Id));
|
||||
|
||||
// assert one admin
|
||||
Assert.assertNotNull(allAdminsBeforeJoin);
|
||||
Assert.assertEquals( 1, allAdminsBeforeJoin.size());
|
||||
|
||||
// Bob to join
|
||||
GroupsTestUtils.joinGroup(repository, bob, group1Id);
|
||||
|
||||
// Have Alice 'invite' Bob to confirm membership
|
||||
GroupsTestUtils.groupInvite(repository, alice, group1Id, bob.getAddress(), 0); // non-expiring invite
|
||||
|
||||
List<String> allMembersAfterJoin = Groups.getAllMembers(repository.getGroupRepository(), List.of(group1Id));
|
||||
|
||||
// alice and bob are members
|
||||
Assert.assertNotNull(allMembersAfterJoin);
|
||||
Assert.assertEquals(2, allMembersAfterJoin.size());
|
||||
|
||||
List<String> allAdminsAfterJoin = Groups.getAllAdmins(repository.getGroupRepository(), List.of(group1Id));
|
||||
|
||||
// assert still one admin
|
||||
Assert.assertNotNull(allAdminsAfterJoin);
|
||||
Assert.assertEquals(1, allAdminsAfterJoin.size());
|
||||
|
||||
List<String> allAdminsFor2Groups = Groups.getAllAdmins(repository.getGroupRepository(), List.of(group1Id, group2Id));
|
||||
|
||||
// assert 2 admins when including the second group
|
||||
Assert.assertNotNull(allAdminsFor2Groups);
|
||||
Assert.assertEquals(2, allAdminsFor2Groups.size());
|
||||
|
||||
List<String> allMembersFor2Groups = Groups.getAllMembers(repository.getGroupRepository(), List.of(group1Id, group2Id));
|
||||
|
||||
// assert 2 members when including the seconds group
|
||||
Assert.assertNotNull(allMembersFor2Groups);
|
||||
Assert.assertEquals(2, allMembersFor2Groups.size());
|
||||
|
||||
GroupsTestUtils.leaveGroup(repository, bob, group1Id);
|
||||
|
||||
List<String> allMembersForAfterBobLeavesGroup1InAllGroups = Groups.getAllMembers(repository.getGroupRepository(), List.of(group1Id, group2Id));
|
||||
|
||||
// alice and bob are members of one group still
|
||||
Assert.assertNotNull(allMembersForAfterBobLeavesGroup1InAllGroups);
|
||||
Assert.assertEquals(2, allMembersForAfterBobLeavesGroup1InAllGroups.size());
|
||||
|
||||
GroupsTestUtils.groupInvite(repository, alice, group1Id, chloe.getAddress(), 3600);
|
||||
GroupsTestUtils.groupInvite(repository, bob, group2Id, chloe.getAddress(), 3600);
|
||||
|
||||
GroupsTestUtils.joinGroup(repository, chloe, group1Id);
|
||||
GroupsTestUtils.joinGroup(repository, chloe, group2Id);
|
||||
|
||||
List<String> allMembersAfterDilbert = Groups.getAllMembers((repository.getGroupRepository()), List.of(group1Id, group2Id));
|
||||
|
||||
// 3 accounts are now members of one group or another
|
||||
Assert.assertNotNull(allMembersAfterDilbert);
|
||||
Assert.assertEquals(3, allMembersAfterDilbert.size());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -31,6 +31,12 @@
|
||||
"blockRewardBatchStartHeight": 999999000,
|
||||
"blockRewardBatchSize": 10,
|
||||
"blockRewardBatchAccountsBlockCount": 3,
|
||||
"mintingGroupIds": [
|
||||
{ "height": 0, "ids": []},
|
||||
{ "height": 5, "ids": [694]},
|
||||
{ "height": 8, "ids": [694, 800]},
|
||||
{ "height": 12, "ids": [800]}
|
||||
],
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
|
Loading…
x
Reference in New Issue
Block a user