forked from Qortal/qortal
Merge pull request #221 from kennycud/master
Minter Group Check Optimizations - Have been tested by 50+ nodes for multiple days. The only thing we have to verify prior to merging the upcoming changes from Alpha, is validate the additional boolean passed in to canMint on line 1521 in current block.java (isMinterValid)
This commit is contained in:
commit
1f9a2edca4
@ -205,10 +205,11 @@ public class Account {
|
||||
* <li>account's address is a member of the minter group</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param isGroupValidated true if this account has already been validated for MINTER Group membership
|
||||
* @return true if account can be considered "minting account"
|
||||
* @throws DataException
|
||||
*/
|
||||
public boolean canMint() throws DataException {
|
||||
public boolean canMint(boolean isGroupValidated) throws DataException {
|
||||
AccountData accountData = this.repository.getAccountRepository().getAccount(this.address);
|
||||
NameRepository nameRepository = this.repository.getNameRepository();
|
||||
GroupRepository groupRepository = this.repository.getGroupRepository();
|
||||
@ -251,9 +252,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() && groupRepository.memberExists(groupIdToMint, myAddress);
|
||||
return accountData.getBlocksMintedPenalty() == 0 && !myName.isEmpty() && (isGroupValidated || groupRepository.memberExists(groupIdToMint, myAddress));
|
||||
} 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
|
||||
if (blockchainHeight >= removeNameCheckHeight) {
|
||||
if (Account.isFounder(accountData.getFlags())) {
|
||||
return accountData.getBlocksMintedPenalty() == 0 && groupRepository.memberExists(groupIdToMint, myAddress);
|
||||
return accountData.getBlocksMintedPenalty() == 0 && (isGroupValidated || groupRepository.memberExists(groupIdToMint, myAddress));
|
||||
} else {
|
||||
return level >= levelToMint && groupRepository.memberExists(groupIdToMint, myAddress);
|
||||
return level >= levelToMint && (isGroupValidated || groupRepository.memberExists(groupIdToMint, myAddress));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -459,7 +459,7 @@ public class AdminResource {
|
||||
|
||||
// Qortal: check reward-share's minting account is still allowed to mint
|
||||
Account rewardShareMintingAccount = new Account(repository, rewardShareData.getMinter());
|
||||
if (!rewardShareMintingAccount.canMint())
|
||||
if (!rewardShareMintingAccount.canMint(false))
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.CANNOT_MINT);
|
||||
|
||||
MintingAccountData mintingAccountData = new MintingAccountData(mintingAccount.getPrivateKey(), mintingAccount.getPublicKey());
|
||||
|
@ -1518,7 +1518,7 @@ public class Block {
|
||||
return false;
|
||||
|
||||
Account mintingAccount = new PublicKeyAccount(this.repository, rewardShareData.getMinterPublicKey());
|
||||
return mintingAccount.canMint();
|
||||
return mintingAccount.canMint(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,7 +148,7 @@ public class BlockMinter extends Thread {
|
||||
}
|
||||
|
||||
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
|
||||
madi.remove();
|
||||
continue;
|
||||
|
@ -13,6 +13,7 @@ import org.qortal.crypto.MemoryPoW;
|
||||
import org.qortal.crypto.Qortal25519Extras;
|
||||
import org.qortal.data.account.MintingAccountData;
|
||||
import org.qortal.data.account.RewardShareData;
|
||||
import org.qortal.data.group.GroupMemberData;
|
||||
import org.qortal.data.network.OnlineAccountData;
|
||||
import org.qortal.network.Network;
|
||||
import org.qortal.network.Peer;
|
||||
@ -224,6 +225,12 @@ public class OnlineAccountsManager {
|
||||
Set<OnlineAccountData> onlineAccountsToAdd = new HashSet<>();
|
||||
Set<OnlineAccountData> onlineAccountsToRemove = new HashSet<>();
|
||||
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) {
|
||||
if (isStopping)
|
||||
return;
|
||||
@ -236,7 +243,7 @@ public class OnlineAccountsManager {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean isValid = this.isValidCurrentAccount(repository, onlineAccountData);
|
||||
boolean isValid = this.isValidCurrentAccount(repository, mintingGroupMemberAddresses, onlineAccountData);
|
||||
if (isValid)
|
||||
onlineAccountsToAdd.add(onlineAccountData);
|
||||
|
||||
@ -315,7 +322,7 @@ public class OnlineAccountsManager {
|
||||
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();
|
||||
if (now == null)
|
||||
return false;
|
||||
@ -350,9 +357,14 @@ public class OnlineAccountsManager {
|
||||
LOGGER.trace(() -> String.format("Rejecting unknown online reward-share public key %s", Base58.encode(rewardSharePublicKey)));
|
||||
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());
|
||||
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
|
||||
LOGGER.trace(() -> String.format("Rejecting online reward-share with non-minting account %s", mintingAccount.getAddress()));
|
||||
return false;
|
||||
@ -539,7 +551,7 @@ public class OnlineAccountsManager {
|
||||
}
|
||||
|
||||
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
|
||||
iterator.remove();
|
||||
continue;
|
||||
|
@ -123,7 +123,7 @@ public class RewardShareTransaction extends Transaction {
|
||||
final boolean isCancellingSharePercent = this.rewardShareTransactionData.getSharePercent() < 0;
|
||||
|
||||
// Creator themselves needs to be allowed to mint (unless cancelling)
|
||||
if (!isCancellingSharePercent && !creator.canMint())
|
||||
if (!isCancellingSharePercent && !creator.canMint(false))
|
||||
return ValidationResult.NOT_MINTING_ACCOUNT;
|
||||
|
||||
// Qortal: special rules in play depending whether recipient is also minter
|
||||
|
@ -74,7 +74,7 @@ public class TransferPrivsTests extends Common {
|
||||
public void testAliceIntoNewAccountTransferPrivs() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
TestAccount alice = Common.getTestAccount(repository, "alice");
|
||||
assertTrue(alice.canMint());
|
||||
assertTrue(alice.canMint(false));
|
||||
|
||||
PrivateKeyAccount aliceMintingAccount = Common.getTestAccount(repository, "alice-reward-share");
|
||||
|
||||
@ -86,8 +86,8 @@ public class TransferPrivsTests extends Common {
|
||||
|
||||
combineAccounts(repository, alice, randomAccount, aliceMintingAccount);
|
||||
|
||||
assertFalse(alice.canMint());
|
||||
assertTrue(randomAccount.canMint());
|
||||
assertFalse(alice.canMint(false));
|
||||
assertTrue(randomAccount.canMint(false));
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,8 +97,8 @@ public class TransferPrivsTests extends Common {
|
||||
TestAccount alice = Common.getTestAccount(repository, "alice");
|
||||
TestAccount dilbert = Common.getTestAccount(repository, "dilbert");
|
||||
|
||||
assertTrue(alice.canMint());
|
||||
assertTrue(dilbert.canMint());
|
||||
assertTrue(alice.canMint(false));
|
||||
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
|
||||
final int expectedPostCombineLevel = dilbert.getLevel() + 1;
|
||||
@ -118,11 +118,11 @@ public class TransferPrivsTests extends Common {
|
||||
|
||||
// Post-combine sender checks
|
||||
checkSenderPostTransfer(postCombineAliceData);
|
||||
assertFalse(alice.canMint());
|
||||
assertFalse(alice.canMint(false));
|
||||
|
||||
// Post-combine recipient checks
|
||||
checkRecipientPostTransfer(preCombineAliceData, preCombineDilbertData, postCombineDilbertData, expectedPostCombineLevel);
|
||||
assertTrue(dilbert.canMint());
|
||||
assertTrue(dilbert.canMint(false));
|
||||
|
||||
// Orphan previous block
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
@ -130,12 +130,12 @@ public class TransferPrivsTests extends Common {
|
||||
// Sender checks
|
||||
AccountData orphanedAliceData = repository.getAccountRepository().getAccount(alice.getAddress());
|
||||
checkAccountDataRestored("sender", preCombineAliceData, orphanedAliceData);
|
||||
assertTrue(alice.canMint());
|
||||
assertTrue(alice.canMint(false));
|
||||
|
||||
// Recipient checks
|
||||
AccountData orphanedDilbertData = repository.getAccountRepository().getAccount(dilbert.getAddress());
|
||||
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 dilbert = Common.getTestAccount(repository, "dilbert");
|
||||
|
||||
assertTrue(dilbert.canMint());
|
||||
assertTrue(alice.canMint());
|
||||
assertTrue(dilbert.canMint(false));
|
||||
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
|
||||
final int expectedPostCombineLevel = dilbert.getLevel() + 1;
|
||||
@ -166,11 +166,11 @@ public class TransferPrivsTests extends Common {
|
||||
|
||||
// Post-combine sender checks
|
||||
checkSenderPostTransfer(postCombineDilbertData);
|
||||
assertFalse(dilbert.canMint());
|
||||
assertFalse(dilbert.canMint(false));
|
||||
|
||||
// Post-combine recipient checks
|
||||
checkRecipientPostTransfer(preCombineDilbertData, preCombineAliceData, postCombineAliceData, expectedPostCombineLevel);
|
||||
assertTrue(alice.canMint());
|
||||
assertTrue(alice.canMint(false));
|
||||
|
||||
// Orphan previous block
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
@ -178,12 +178,12 @@ public class TransferPrivsTests extends Common {
|
||||
// Sender checks
|
||||
AccountData orphanedDilbertData = repository.getAccountRepository().getAccount(dilbert.getAddress());
|
||||
checkAccountDataRestored("sender", preCombineDilbertData, orphanedDilbertData);
|
||||
assertTrue(dilbert.canMint());
|
||||
assertTrue(dilbert.canMint(false));
|
||||
|
||||
// Recipient checks
|
||||
AccountData orphanedAliceData = repository.getAccountRepository().getAccount(alice.getAddress());
|
||||
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 dilbert = Common.getTestAccount(repository, "dilbert");
|
||||
|
||||
assertTrue(dilbert.canMint());
|
||||
assertFalse(chloe.canMint());
|
||||
assertTrue(dilbert.canMint(false));
|
||||
assertFalse(chloe.canMint(false));
|
||||
|
||||
// COMBINE DILBERT INTO CHLOE
|
||||
|
||||
@ -225,16 +225,16 @@ public class TransferPrivsTests extends Common {
|
||||
|
||||
// Post-combine sender checks
|
||||
checkSenderPostTransfer(post1stCombineDilbertData);
|
||||
assertFalse(dilbert.canMint());
|
||||
assertFalse(dilbert.canMint(false));
|
||||
|
||||
// Post-combine recipient checks
|
||||
checkRecipientPostTransfer(pre1stCombineDilbertData, pre1stCombineChloeData, post1stCombineChloeData, expectedPost1stCombineLevel);
|
||||
assertTrue(chloe.canMint());
|
||||
assertTrue(chloe.canMint(false));
|
||||
|
||||
// COMBINE ALICE INTO CHLOE
|
||||
|
||||
assertTrue(alice.canMint());
|
||||
assertTrue(chloe.canMint());
|
||||
assertTrue(alice.canMint(false));
|
||||
assertTrue(chloe.canMint(false));
|
||||
|
||||
// Alice needs to mint enough blocks to surpass Chloe's level post-combine
|
||||
final int expectedPost2ndCombineLevel = chloe.getLevel() + 1;
|
||||
@ -254,11 +254,11 @@ public class TransferPrivsTests extends Common {
|
||||
|
||||
// Post-combine sender checks
|
||||
checkSenderPostTransfer(post2ndCombineAliceData);
|
||||
assertFalse(alice.canMint());
|
||||
assertFalse(alice.canMint(false));
|
||||
|
||||
// Post-combine recipient checks
|
||||
checkRecipientPostTransfer(pre2ndCombineAliceData, pre2ndCombineChloeData, post2ndCombineChloeData, expectedPost2ndCombineLevel);
|
||||
assertTrue(chloe.canMint());
|
||||
assertTrue(chloe.canMint(false));
|
||||
|
||||
// Orphan 2nd combine
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
@ -266,12 +266,12 @@ public class TransferPrivsTests extends Common {
|
||||
// Sender checks
|
||||
AccountData orphanedAliceData = repository.getAccountRepository().getAccount(alice.getAddress());
|
||||
checkAccountDataRestored("sender", pre2ndCombineAliceData, orphanedAliceData);
|
||||
assertTrue(alice.canMint());
|
||||
assertTrue(alice.canMint(false));
|
||||
|
||||
// Recipient checks
|
||||
AccountData orphanedChloeData = repository.getAccountRepository().getAccount(chloe.getAddress());
|
||||
checkAccountDataRestored("recipient", pre2ndCombineChloeData, orphanedChloeData);
|
||||
assertTrue(chloe.canMint());
|
||||
assertTrue(chloe.canMint(false));
|
||||
|
||||
// Orphan 1nd combine
|
||||
BlockUtils.orphanToBlock(repository, pre1stCombineBlockHeight);
|
||||
@ -279,7 +279,7 @@ public class TransferPrivsTests extends Common {
|
||||
// Sender checks
|
||||
AccountData orphanedDilbertData = repository.getAccountRepository().getAccount(dilbert.getAddress());
|
||||
checkAccountDataRestored("sender", pre1stCombineDilbertData, orphanedDilbertData);
|
||||
assertTrue(dilbert.canMint());
|
||||
assertTrue(dilbert.canMint(false));
|
||||
|
||||
// Recipient checks
|
||||
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
|
||||
BlockUtils.orphanToBlock(repository, 1);
|
||||
assertFalse(chloe.canMint());
|
||||
assertFalse(chloe.canMint(false));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user