minter group check optimizations

This commit is contained in:
kennycud 2024-11-20 19:12:21 -08:00
parent f277611d31
commit b0d43a1890
7 changed files with 53 additions and 40 deletions

View File

@ -205,10 +205,11 @@ public class Account {
* <li>account's address is a member of the minter group</li> * <li>account's address is a member of the minter group</li>
* </ul> * </ul>
* *
* @param isGroupValidated true if this account has already been validated for MINTER Group membership
* @return true if account can be considered "minting account" * @return true if account can be considered "minting account"
* @throws DataException * @throws DataException
*/ */
public boolean canMint() throws DataException { public boolean canMint(boolean isGroupValidated) throws DataException {
AccountData accountData = this.repository.getAccountRepository().getAccount(this.address); AccountData accountData = this.repository.getAccountRepository().getAccount(this.address);
NameRepository nameRepository = this.repository.getNameRepository(); NameRepository nameRepository = this.repository.getNameRepository();
GroupRepository groupRepository = this.repository.getGroupRepository(); GroupRepository groupRepository = this.repository.getGroupRepository();
@ -251,9 +252,9 @@ public class Account {
if (blockchainHeight >= groupCheckHeight && blockchainHeight < removeNameCheckHeight) { if (blockchainHeight >= groupCheckHeight && blockchainHeight < removeNameCheckHeight) {
List<NameData> myName = nameRepository.getNamesByOwner(myAddress); List<NameData> myName = nameRepository.getNamesByOwner(myAddress);
if (Account.isFounder(accountData.getFlags())) { if (Account.isFounder(accountData.getFlags())) {
return accountData.getBlocksMintedPenalty() == 0 && !myName.isEmpty() && groupRepository.memberExists(groupIdToMint, myAddress); return accountData.getBlocksMintedPenalty() == 0 && !myName.isEmpty() && (isGroupValidated || groupRepository.memberExists(groupIdToMint, myAddress));
} else { } else {
return level >= levelToMint && !myName.isEmpty() && groupRepository.memberExists(groupIdToMint, myAddress); return level >= levelToMint && !myName.isEmpty() && (isGroupValidated || groupRepository.memberExists(groupIdToMint, myAddress));
} }
} }
@ -262,9 +263,9 @@ public class Account {
// Account's address is a member of the minter group // Account's address is a member of the minter group
if (blockchainHeight >= removeNameCheckHeight) { if (blockchainHeight >= removeNameCheckHeight) {
if (Account.isFounder(accountData.getFlags())) { if (Account.isFounder(accountData.getFlags())) {
return accountData.getBlocksMintedPenalty() == 0 && groupRepository.memberExists(groupIdToMint, myAddress); return accountData.getBlocksMintedPenalty() == 0 && (isGroupValidated || groupRepository.memberExists(groupIdToMint, myAddress));
} else { } else {
return level >= levelToMint && groupRepository.memberExists(groupIdToMint, myAddress); return level >= levelToMint && (isGroupValidated || groupRepository.memberExists(groupIdToMint, myAddress));
} }
} }

View File

@ -459,7 +459,7 @@ public class AdminResource {
// Qortal: check reward-share's minting account is still allowed to mint // Qortal: check reward-share's minting account is still allowed to mint
Account rewardShareMintingAccount = new Account(repository, rewardShareData.getMinter()); Account rewardShareMintingAccount = new Account(repository, rewardShareData.getMinter());
if (!rewardShareMintingAccount.canMint()) if (!rewardShareMintingAccount.canMint(false))
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.CANNOT_MINT); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.CANNOT_MINT);
MintingAccountData mintingAccountData = new MintingAccountData(mintingAccount.getPrivateKey(), mintingAccount.getPublicKey()); MintingAccountData mintingAccountData = new MintingAccountData(mintingAccount.getPrivateKey(), mintingAccount.getPublicKey());

View File

@ -1518,7 +1518,7 @@ public class Block {
return false; return false;
Account mintingAccount = new PublicKeyAccount(this.repository, rewardShareData.getMinterPublicKey()); Account mintingAccount = new PublicKeyAccount(this.repository, rewardShareData.getMinterPublicKey());
return mintingAccount.canMint(); return mintingAccount.canMint(false);
} }
/** /**

View File

@ -148,7 +148,7 @@ public class BlockMinter extends Thread {
} }
Account mintingAccount = new Account(repository, rewardShareData.getMinter()); Account mintingAccount = new Account(repository, rewardShareData.getMinter());
if (!mintingAccount.canMint()) { if (!mintingAccount.canMint(true)) {
// Minting-account component of reward-share can no longer mint - disregard // Minting-account component of reward-share can no longer mint - disregard
madi.remove(); madi.remove();
continue; continue;

View File

@ -13,6 +13,7 @@ import org.qortal.crypto.MemoryPoW;
import org.qortal.crypto.Qortal25519Extras; import org.qortal.crypto.Qortal25519Extras;
import org.qortal.data.account.MintingAccountData; import org.qortal.data.account.MintingAccountData;
import org.qortal.data.account.RewardShareData; import org.qortal.data.account.RewardShareData;
import org.qortal.data.group.GroupMemberData;
import org.qortal.data.network.OnlineAccountData; import org.qortal.data.network.OnlineAccountData;
import org.qortal.network.Network; import org.qortal.network.Network;
import org.qortal.network.Peer; import org.qortal.network.Peer;
@ -224,6 +225,12 @@ public class OnlineAccountsManager {
Set<OnlineAccountData> onlineAccountsToAdd = new HashSet<>(); Set<OnlineAccountData> onlineAccountsToAdd = new HashSet<>();
Set<OnlineAccountData> onlineAccountsToRemove = new HashSet<>(); Set<OnlineAccountData> onlineAccountsToRemove = new HashSet<>();
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
List<String> mintingGroupMemberAddresses
= repository.getGroupRepository()
.getGroupMembers(BlockChain.getInstance().getMintingGroupId()).stream()
.map(GroupMemberData::getMember)
.collect(Collectors.toList());
for (OnlineAccountData onlineAccountData : this.onlineAccountsImportQueue) { for (OnlineAccountData onlineAccountData : this.onlineAccountsImportQueue) {
if (isStopping) if (isStopping)
return; return;
@ -236,7 +243,7 @@ public class OnlineAccountsManager {
continue; continue;
} }
boolean isValid = this.isValidCurrentAccount(repository, onlineAccountData); boolean isValid = this.isValidCurrentAccount(repository, mintingGroupMemberAddresses, onlineAccountData);
if (isValid) if (isValid)
onlineAccountsToAdd.add(onlineAccountData); onlineAccountsToAdd.add(onlineAccountData);
@ -315,7 +322,7 @@ public class OnlineAccountsManager {
return inplaceArray; return inplaceArray;
} }
private static boolean isValidCurrentAccount(Repository repository, OnlineAccountData onlineAccountData) throws DataException { private static boolean isValidCurrentAccount(Repository repository, List<String> mintingGroupMemberAddresses, OnlineAccountData onlineAccountData) throws DataException {
final Long now = NTP.getTime(); final Long now = NTP.getTime();
if (now == null) if (now == null)
return false; return false;
@ -350,9 +357,14 @@ public class OnlineAccountsManager {
LOGGER.trace(() -> String.format("Rejecting unknown online reward-share public key %s", Base58.encode(rewardSharePublicKey))); LOGGER.trace(() -> String.format("Rejecting unknown online reward-share public key %s", Base58.encode(rewardSharePublicKey)));
return false; return false;
} }
// reject account address that are not in the MINTER Group
else if( !mintingGroupMemberAddresses.contains(rewardShareData.getMinter())) {
LOGGER.trace(() -> String.format("Rejecting online reward-share that is not in MINTER Group, account %s", rewardShareData.getMinter()));
return false;
}
Account mintingAccount = new Account(repository, rewardShareData.getMinter()); Account mintingAccount = new Account(repository, rewardShareData.getMinter());
if (!mintingAccount.canMint()) { if (!mintingAccount.canMint(true)) { // group validation is a few lines above
// Minting-account component of reward-share can no longer mint - disregard // Minting-account component of reward-share can no longer mint - disregard
LOGGER.trace(() -> String.format("Rejecting online reward-share with non-minting account %s", mintingAccount.getAddress())); LOGGER.trace(() -> String.format("Rejecting online reward-share with non-minting account %s", mintingAccount.getAddress()));
return false; return false;
@ -539,7 +551,7 @@ public class OnlineAccountsManager {
} }
Account mintingAccount = new Account(repository, rewardShareData.getMinter()); Account mintingAccount = new Account(repository, rewardShareData.getMinter());
if (!mintingAccount.canMint()) { if (!mintingAccount.canMint(true)) {
// Minting-account component of reward-share can no longer mint - disregard // Minting-account component of reward-share can no longer mint - disregard
iterator.remove(); iterator.remove();
continue; continue;

View File

@ -123,7 +123,7 @@ public class RewardShareTransaction extends Transaction {
final boolean isCancellingSharePercent = this.rewardShareTransactionData.getSharePercent() < 0; final boolean isCancellingSharePercent = this.rewardShareTransactionData.getSharePercent() < 0;
// Creator themselves needs to be allowed to mint (unless cancelling) // Creator themselves needs to be allowed to mint (unless cancelling)
if (!isCancellingSharePercent && !creator.canMint()) if (!isCancellingSharePercent && !creator.canMint(false))
return ValidationResult.NOT_MINTING_ACCOUNT; return ValidationResult.NOT_MINTING_ACCOUNT;
// Qortal: special rules in play depending whether recipient is also minter // Qortal: special rules in play depending whether recipient is also minter

View File

@ -74,7 +74,7 @@ public class TransferPrivsTests extends Common {
public void testAliceIntoNewAccountTransferPrivs() throws DataException { public void testAliceIntoNewAccountTransferPrivs() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
TestAccount alice = Common.getTestAccount(repository, "alice"); TestAccount alice = Common.getTestAccount(repository, "alice");
assertTrue(alice.canMint()); assertTrue(alice.canMint(false));
PrivateKeyAccount aliceMintingAccount = Common.getTestAccount(repository, "alice-reward-share"); PrivateKeyAccount aliceMintingAccount = Common.getTestAccount(repository, "alice-reward-share");
@ -86,8 +86,8 @@ public class TransferPrivsTests extends Common {
combineAccounts(repository, alice, randomAccount, aliceMintingAccount); combineAccounts(repository, alice, randomAccount, aliceMintingAccount);
assertFalse(alice.canMint()); assertFalse(alice.canMint(false));
assertTrue(randomAccount.canMint()); assertTrue(randomAccount.canMint(false));
} }
} }
@ -97,8 +97,8 @@ public class TransferPrivsTests extends Common {
TestAccount alice = Common.getTestAccount(repository, "alice"); TestAccount alice = Common.getTestAccount(repository, "alice");
TestAccount dilbert = Common.getTestAccount(repository, "dilbert"); TestAccount dilbert = Common.getTestAccount(repository, "dilbert");
assertTrue(alice.canMint()); assertTrue(alice.canMint(false));
assertTrue(dilbert.canMint()); assertTrue(dilbert.canMint(false));
// Dilbert has level, Alice does not so we need Alice to mint enough blocks to bump Dilbert's level post-combine // Dilbert has level, Alice does not so we need Alice to mint enough blocks to bump Dilbert's level post-combine
final int expectedPostCombineLevel = dilbert.getLevel() + 1; final int expectedPostCombineLevel = dilbert.getLevel() + 1;
@ -118,11 +118,11 @@ public class TransferPrivsTests extends Common {
// Post-combine sender checks // Post-combine sender checks
checkSenderPostTransfer(postCombineAliceData); checkSenderPostTransfer(postCombineAliceData);
assertFalse(alice.canMint()); assertFalse(alice.canMint(false));
// Post-combine recipient checks // Post-combine recipient checks
checkRecipientPostTransfer(preCombineAliceData, preCombineDilbertData, postCombineDilbertData, expectedPostCombineLevel); checkRecipientPostTransfer(preCombineAliceData, preCombineDilbertData, postCombineDilbertData, expectedPostCombineLevel);
assertTrue(dilbert.canMint()); assertTrue(dilbert.canMint(false));
// Orphan previous block // Orphan previous block
BlockUtils.orphanLastBlock(repository); BlockUtils.orphanLastBlock(repository);
@ -130,12 +130,12 @@ public class TransferPrivsTests extends Common {
// Sender checks // Sender checks
AccountData orphanedAliceData = repository.getAccountRepository().getAccount(alice.getAddress()); AccountData orphanedAliceData = repository.getAccountRepository().getAccount(alice.getAddress());
checkAccountDataRestored("sender", preCombineAliceData, orphanedAliceData); checkAccountDataRestored("sender", preCombineAliceData, orphanedAliceData);
assertTrue(alice.canMint()); assertTrue(alice.canMint(false));
// Recipient checks // Recipient checks
AccountData orphanedDilbertData = repository.getAccountRepository().getAccount(dilbert.getAddress()); AccountData orphanedDilbertData = repository.getAccountRepository().getAccount(dilbert.getAddress());
checkAccountDataRestored("recipient", preCombineDilbertData, orphanedDilbertData); checkAccountDataRestored("recipient", preCombineDilbertData, orphanedDilbertData);
assertTrue(dilbert.canMint()); assertTrue(dilbert.canMint(false));
} }
} }
@ -145,8 +145,8 @@ public class TransferPrivsTests extends Common {
TestAccount alice = Common.getTestAccount(repository, "alice"); TestAccount alice = Common.getTestAccount(repository, "alice");
TestAccount dilbert = Common.getTestAccount(repository, "dilbert"); TestAccount dilbert = Common.getTestAccount(repository, "dilbert");
assertTrue(dilbert.canMint()); assertTrue(dilbert.canMint(false));
assertTrue(alice.canMint()); assertTrue(alice.canMint(false));
// Dilbert has level, Alice does not so we need Alice to mint enough blocks to surpass Dilbert's level post-combine // Dilbert has level, Alice does not so we need Alice to mint enough blocks to surpass Dilbert's level post-combine
final int expectedPostCombineLevel = dilbert.getLevel() + 1; final int expectedPostCombineLevel = dilbert.getLevel() + 1;
@ -166,11 +166,11 @@ public class TransferPrivsTests extends Common {
// Post-combine sender checks // Post-combine sender checks
checkSenderPostTransfer(postCombineDilbertData); checkSenderPostTransfer(postCombineDilbertData);
assertFalse(dilbert.canMint()); assertFalse(dilbert.canMint(false));
// Post-combine recipient checks // Post-combine recipient checks
checkRecipientPostTransfer(preCombineDilbertData, preCombineAliceData, postCombineAliceData, expectedPostCombineLevel); checkRecipientPostTransfer(preCombineDilbertData, preCombineAliceData, postCombineAliceData, expectedPostCombineLevel);
assertTrue(alice.canMint()); assertTrue(alice.canMint(false));
// Orphan previous block // Orphan previous block
BlockUtils.orphanLastBlock(repository); BlockUtils.orphanLastBlock(repository);
@ -178,12 +178,12 @@ public class TransferPrivsTests extends Common {
// Sender checks // Sender checks
AccountData orphanedDilbertData = repository.getAccountRepository().getAccount(dilbert.getAddress()); AccountData orphanedDilbertData = repository.getAccountRepository().getAccount(dilbert.getAddress());
checkAccountDataRestored("sender", preCombineDilbertData, orphanedDilbertData); checkAccountDataRestored("sender", preCombineDilbertData, orphanedDilbertData);
assertTrue(dilbert.canMint()); assertTrue(dilbert.canMint(false));
// Recipient checks // Recipient checks
AccountData orphanedAliceData = repository.getAccountRepository().getAccount(alice.getAddress()); AccountData orphanedAliceData = repository.getAccountRepository().getAccount(alice.getAddress());
checkAccountDataRestored("recipient", preCombineAliceData, orphanedAliceData); checkAccountDataRestored("recipient", preCombineAliceData, orphanedAliceData);
assertTrue(alice.canMint()); assertTrue(alice.canMint(false));
} }
} }
@ -202,8 +202,8 @@ public class TransferPrivsTests extends Common {
TestAccount chloe = Common.getTestAccount(repository, "chloe"); TestAccount chloe = Common.getTestAccount(repository, "chloe");
TestAccount dilbert = Common.getTestAccount(repository, "dilbert"); TestAccount dilbert = Common.getTestAccount(repository, "dilbert");
assertTrue(dilbert.canMint()); assertTrue(dilbert.canMint(false));
assertFalse(chloe.canMint()); assertFalse(chloe.canMint(false));
// COMBINE DILBERT INTO CHLOE // COMBINE DILBERT INTO CHLOE
@ -225,16 +225,16 @@ public class TransferPrivsTests extends Common {
// Post-combine sender checks // Post-combine sender checks
checkSenderPostTransfer(post1stCombineDilbertData); checkSenderPostTransfer(post1stCombineDilbertData);
assertFalse(dilbert.canMint()); assertFalse(dilbert.canMint(false));
// Post-combine recipient checks // Post-combine recipient checks
checkRecipientPostTransfer(pre1stCombineDilbertData, pre1stCombineChloeData, post1stCombineChloeData, expectedPost1stCombineLevel); checkRecipientPostTransfer(pre1stCombineDilbertData, pre1stCombineChloeData, post1stCombineChloeData, expectedPost1stCombineLevel);
assertTrue(chloe.canMint()); assertTrue(chloe.canMint(false));
// COMBINE ALICE INTO CHLOE // COMBINE ALICE INTO CHLOE
assertTrue(alice.canMint()); assertTrue(alice.canMint(false));
assertTrue(chloe.canMint()); assertTrue(chloe.canMint(false));
// Alice needs to mint enough blocks to surpass Chloe's level post-combine // Alice needs to mint enough blocks to surpass Chloe's level post-combine
final int expectedPost2ndCombineLevel = chloe.getLevel() + 1; final int expectedPost2ndCombineLevel = chloe.getLevel() + 1;
@ -254,11 +254,11 @@ public class TransferPrivsTests extends Common {
// Post-combine sender checks // Post-combine sender checks
checkSenderPostTransfer(post2ndCombineAliceData); checkSenderPostTransfer(post2ndCombineAliceData);
assertFalse(alice.canMint()); assertFalse(alice.canMint(false));
// Post-combine recipient checks // Post-combine recipient checks
checkRecipientPostTransfer(pre2ndCombineAliceData, pre2ndCombineChloeData, post2ndCombineChloeData, expectedPost2ndCombineLevel); checkRecipientPostTransfer(pre2ndCombineAliceData, pre2ndCombineChloeData, post2ndCombineChloeData, expectedPost2ndCombineLevel);
assertTrue(chloe.canMint()); assertTrue(chloe.canMint(false));
// Orphan 2nd combine // Orphan 2nd combine
BlockUtils.orphanLastBlock(repository); BlockUtils.orphanLastBlock(repository);
@ -266,12 +266,12 @@ public class TransferPrivsTests extends Common {
// Sender checks // Sender checks
AccountData orphanedAliceData = repository.getAccountRepository().getAccount(alice.getAddress()); AccountData orphanedAliceData = repository.getAccountRepository().getAccount(alice.getAddress());
checkAccountDataRestored("sender", pre2ndCombineAliceData, orphanedAliceData); checkAccountDataRestored("sender", pre2ndCombineAliceData, orphanedAliceData);
assertTrue(alice.canMint()); assertTrue(alice.canMint(false));
// Recipient checks // Recipient checks
AccountData orphanedChloeData = repository.getAccountRepository().getAccount(chloe.getAddress()); AccountData orphanedChloeData = repository.getAccountRepository().getAccount(chloe.getAddress());
checkAccountDataRestored("recipient", pre2ndCombineChloeData, orphanedChloeData); checkAccountDataRestored("recipient", pre2ndCombineChloeData, orphanedChloeData);
assertTrue(chloe.canMint()); assertTrue(chloe.canMint(false));
// Orphan 1nd combine // Orphan 1nd combine
BlockUtils.orphanToBlock(repository, pre1stCombineBlockHeight); BlockUtils.orphanToBlock(repository, pre1stCombineBlockHeight);
@ -279,7 +279,7 @@ public class TransferPrivsTests extends Common {
// Sender checks // Sender checks
AccountData orphanedDilbertData = repository.getAccountRepository().getAccount(dilbert.getAddress()); AccountData orphanedDilbertData = repository.getAccountRepository().getAccount(dilbert.getAddress());
checkAccountDataRestored("sender", pre1stCombineDilbertData, orphanedDilbertData); checkAccountDataRestored("sender", pre1stCombineDilbertData, orphanedDilbertData);
assertTrue(dilbert.canMint()); assertTrue(dilbert.canMint(false));
// Recipient checks // Recipient checks
orphanedChloeData = repository.getAccountRepository().getAccount(chloe.getAddress()); orphanedChloeData = repository.getAccountRepository().getAccount(chloe.getAddress());
@ -287,7 +287,7 @@ public class TransferPrivsTests extends Common {
// Chloe canMint() would return true here due to Alice-Chloe reward-share minting at top of method, so undo that minting by orphaning back to block 1 // Chloe canMint() would return true here due to Alice-Chloe reward-share minting at top of method, so undo that minting by orphaning back to block 1
BlockUtils.orphanToBlock(repository, 1); BlockUtils.orphanToBlock(repository, 1);
assertFalse(chloe.canMint()); assertFalse(chloe.canMint(false));
} }
} }