forked from Qortal/qortal
Merge pull request #241 from crowetic/master
Selective acceptance of recent PRs to Qortal master branch, and updated start.sh script. See description for details.
This commit is contained in:
commit
749143e98e
@ -349,10 +349,28 @@ public class Account {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 'effective' minting level, or zero if reward-share does not exist.
|
||||
* Returns reward-share minting address, or unknown if reward-share does not exist.
|
||||
*
|
||||
* @param repository
|
||||
* @param rewardSharePublicKey
|
||||
* @return address or unknown
|
||||
* @throws DataException
|
||||
*/
|
||||
public static String getRewardShareMintingAddress(Repository repository, byte[] rewardSharePublicKey) throws DataException {
|
||||
// Find actual minter address
|
||||
RewardShareData rewardShareData = repository.getAccountRepository().getRewardShare(rewardSharePublicKey);
|
||||
|
||||
if (rewardShareData == null)
|
||||
return "Unknown";
|
||||
|
||||
return rewardShareData.getMinter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 'effective' minting level, or zero if reward-share does not exist.
|
||||
*
|
||||
* @param repository
|
||||
* @param rewardSharePublicKey
|
||||
* @return 0+
|
||||
* @throws DataException
|
||||
*/
|
||||
|
@ -1,7 +1,13 @@
|
||||
package org.qortal.api.model;
|
||||
|
||||
import org.qortal.account.Account;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.RepositoryManager;
|
||||
import org.qortal.repository.Repository;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
// All properties to be converted to JSON via JAXB
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@ -47,4 +53,31 @@ public class ApiOnlineAccount {
|
||||
return this.recipientAddress;
|
||||
}
|
||||
|
||||
public int getMinterLevelFromPublicKey() {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
return Account.getRewardShareEffectiveMintingLevel(repository, this.rewardSharePublicKey);
|
||||
} catch (DataException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getIsMember() {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
return repository.getGroupRepository().memberExists(694, getMinterAddress());
|
||||
} catch (DataException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// JAXB special
|
||||
|
||||
@XmlElement(name = "minterLevel")
|
||||
protected int getMinterLevel() {
|
||||
return getMinterLevelFromPublicKey();
|
||||
}
|
||||
|
||||
@XmlElement(name = "isMinterMember")
|
||||
protected boolean getMinterMember() {
|
||||
return getIsMember();
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import java.math.BigInteger;
|
||||
public class BlockMintingInfo {
|
||||
|
||||
public byte[] minterPublicKey;
|
||||
public String minterAddress;
|
||||
public int minterLevel;
|
||||
public int onlineAccountsCount;
|
||||
public BigDecimal maxDistance;
|
||||
@ -19,5 +20,4 @@ public class BlockMintingInfo {
|
||||
|
||||
public BlockMintingInfo() {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -542,6 +542,7 @@ public class BlocksResource {
|
||||
}
|
||||
}
|
||||
|
||||
String minterAddress = Account.getRewardShareMintingAddress(repository, blockData.getMinterPublicKey());
|
||||
int minterLevel = Account.getRewardShareEffectiveMintingLevel(repository, blockData.getMinterPublicKey());
|
||||
if (minterLevel == 0)
|
||||
// This may be unavailable when requesting a trimmed block
|
||||
@ -554,6 +555,7 @@ public class BlocksResource {
|
||||
|
||||
BlockMintingInfo blockMintingInfo = new BlockMintingInfo();
|
||||
blockMintingInfo.minterPublicKey = blockData.getMinterPublicKey();
|
||||
blockMintingInfo.minterAddress = minterAddress;
|
||||
blockMintingInfo.minterLevel = minterLevel;
|
||||
blockMintingInfo.onlineAccountsCount = blockData.getOnlineAccountsCount();
|
||||
blockMintingInfo.maxDistance = new BigDecimal(block.MAX_DISTANCE);
|
||||
@ -887,5 +889,4 @@ public class BlocksResource {
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ public class Block {
|
||||
|
||||
private final Account recipientAccount;
|
||||
private final AccountData recipientAccountData;
|
||||
|
||||
|
||||
final BlockChain blockChain = BlockChain.getInstance();
|
||||
|
||||
ExpandedAccount(Repository repository, RewardShareData rewardShareData) throws DataException {
|
||||
@ -414,6 +414,21 @@ public class Block {
|
||||
});
|
||||
}
|
||||
|
||||
// After feature trigger, remove any online accounts that are not minter group member
|
||||
if (height >= BlockChain.getInstance().getGroupMemberCheckHeight()) {
|
||||
onlineAccounts.removeIf(a -> {
|
||||
try {
|
||||
int groupId = BlockChain.getInstance().getMintingGroupId();
|
||||
String address = Account.getRewardShareMintingAddress(repository, a.getPublicKey());
|
||||
boolean isMinterGroupMember = repository.getGroupRepository().memberExists(groupId, address);
|
||||
return !isMinterGroupMember;
|
||||
} catch (DataException e) {
|
||||
// Something went wrong, so remove the account
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (onlineAccounts.isEmpty()) {
|
||||
LOGGER.debug("No online accounts - not even our own?");
|
||||
return null;
|
||||
@ -721,19 +736,19 @@ public class Block {
|
||||
List<ExpandedAccount> expandedAccounts = new ArrayList<>();
|
||||
|
||||
for (RewardShareData rewardShare : this.cachedOnlineRewardShares) {
|
||||
if (this.getBlockData().getHeight() < BlockChain.getInstance().getFixBatchRewardHeight()) {
|
||||
int groupId = BlockChain.getInstance().getMintingGroupId();
|
||||
String address = rewardShare.getMinter();
|
||||
boolean isMinterGroupMember = repository.getGroupRepository().memberExists(groupId, address);
|
||||
|
||||
if (this.getBlockData().getHeight() < BlockChain.getInstance().getFixBatchRewardHeight())
|
||||
expandedAccounts.add(new ExpandedAccount(repository, rewardShare));
|
||||
|
||||
if (this.getBlockData().getHeight() >= BlockChain.getInstance().getFixBatchRewardHeight() && isMinterGroupMember)
|
||||
expandedAccounts.add(new ExpandedAccount(repository, rewardShare));
|
||||
}
|
||||
if (this.getBlockData().getHeight() >= BlockChain.getInstance().getFixBatchRewardHeight()) {
|
||||
boolean isMinterGroupMember = repository.getGroupRepository().memberExists(BlockChain.getInstance().getMintingGroupId(), rewardShare.getMinter());
|
||||
if (isMinterGroupMember) {
|
||||
expandedAccounts.add(new ExpandedAccount(repository, rewardShare));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.cachedExpandedAccounts = expandedAccounts;
|
||||
LOGGER.trace(() -> String.format("Online reward-shares after expanded accounts %s", this.cachedOnlineRewardShares));
|
||||
|
||||
return this.cachedExpandedAccounts;
|
||||
}
|
||||
@ -1143,8 +1158,17 @@ public class Block {
|
||||
if (this.getBlockData().getHeight() >= BlockChain.getInstance().getOnlineAccountMinterLevelValidationHeight()) {
|
||||
List<ExpandedAccount> expandedAccounts = this.getExpandedAccounts();
|
||||
for (ExpandedAccount account : expandedAccounts) {
|
||||
int groupId = BlockChain.getInstance().getMintingGroupId();
|
||||
String address = account.getMintingAccount().getAddress();
|
||||
boolean isMinterGroupMember = repository.getGroupRepository().memberExists(groupId, address);
|
||||
|
||||
if (account.getMintingAccount().getEffectiveMintingLevel() == 0)
|
||||
return ValidationResult.ONLINE_ACCOUNTS_INVALID;
|
||||
|
||||
if (this.getBlockData().getHeight() >= BlockChain.getInstance().getFixBatchRewardHeight()) {
|
||||
if (!isMinterGroupMember)
|
||||
return ValidationResult.ONLINE_ACCOUNTS_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1273,6 +1297,7 @@ public class Block {
|
||||
|
||||
// Online Accounts
|
||||
ValidationResult onlineAccountsResult = this.areOnlineAccountsValid();
|
||||
LOGGER.trace("Accounts valid = {}", onlineAccountsResult);
|
||||
if (onlineAccountsResult != ValidationResult.OK)
|
||||
return onlineAccountsResult;
|
||||
|
||||
@ -1361,7 +1386,7 @@ public class Block {
|
||||
// Check transaction can even be processed
|
||||
validationResult = transaction.isProcessable();
|
||||
if (validationResult != Transaction.ValidationResult.OK) {
|
||||
LOGGER.info(String.format("Error during transaction validation, tx %s: %s", Base58.encode(transactionData.getSignature()), validationResult.name()));
|
||||
LOGGER.debug(String.format("Error during transaction validation, tx %s: %s", Base58.encode(transactionData.getSignature()), validationResult.name()));
|
||||
return ValidationResult.TRANSACTION_INVALID;
|
||||
}
|
||||
|
||||
@ -1562,6 +1587,7 @@ public class Block {
|
||||
this.blockData.setHeight(blockchainHeight + 1);
|
||||
|
||||
LOGGER.trace(() -> String.format("Processing block %d", this.blockData.getHeight()));
|
||||
LOGGER.trace(() -> String.format("Online Reward Shares in process %s", this.cachedOnlineRewardShares));
|
||||
|
||||
if (this.blockData.getHeight() > 1) {
|
||||
|
||||
@ -2280,7 +2306,6 @@ public class Block {
|
||||
// Select the correct set of share bins based on block height
|
||||
List<AccountLevelShareBin> accountLevelShareBinsForBlock = (this.blockData.getHeight() >= BlockChain.getInstance().getSharesByLevelV2Height()) ?
|
||||
BlockChain.getInstance().getAccountLevelShareBinsV2() : BlockChain.getInstance().getAccountLevelShareBinsV1();
|
||||
|
||||
// Determine reward candidates based on account level
|
||||
// This needs a deep copy, so the shares can be modified when tiers aren't activated yet
|
||||
List<AccountLevelShareBin> accountLevelShareBins = new ArrayList<>();
|
||||
@ -2570,9 +2595,11 @@ public class Block {
|
||||
return;
|
||||
|
||||
int minterLevel = Account.getRewardShareEffectiveMintingLevel(this.repository, this.getMinter().getPublicKey());
|
||||
String minterAddress = Account.getRewardShareMintingAddress(this.repository, this.getMinter().getPublicKey());
|
||||
|
||||
LOGGER.debug(String.format("======= BLOCK %d (%.8s) =======", this.getBlockData().getHeight(), Base58.encode(this.getSignature())));
|
||||
LOGGER.debug(String.format("Timestamp: %d", this.getBlockData().getTimestamp()));
|
||||
LOGGER.debug(String.format("Minter address: %s", minterAddress));
|
||||
LOGGER.debug(String.format("Minter level: %d", minterLevel));
|
||||
LOGGER.debug(String.format("Online accounts: %d", this.getBlockData().getOnlineAccountsCount()));
|
||||
LOGGER.debug(String.format("AT count: %d", this.getBlockData().getATCount()));
|
||||
|
@ -1,8 +1,11 @@
|
||||
package org.qortal.data.block;
|
||||
|
||||
import com.google.common.primitives.Bytes;
|
||||
import org.qortal.account.Account;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.crypto.Crypto;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
import org.qortal.repository.RepositoryManager;
|
||||
import org.qortal.settings.Settings;
|
||||
import org.qortal.utils.NTP;
|
||||
|
||||
@ -224,7 +227,7 @@ public class BlockData implements Serializable {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public boolean isTrimmed() {
|
||||
long onlineAccountSignaturesTrimmedTimestamp = NTP.getTime() - BlockChain.getInstance().getOnlineAccountSignaturesMaxLifetime();
|
||||
long currentTrimmableTimestamp = NTP.getTime() - Settings.getInstance().getAtStatesMaxLifetime();
|
||||
@ -232,11 +235,31 @@ public class BlockData implements Serializable {
|
||||
return blockTimestamp < onlineAccountSignaturesTrimmedTimestamp && blockTimestamp < currentTrimmableTimestamp;
|
||||
}
|
||||
|
||||
public String getMinterAddressFromPublicKey() {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
return Account.getRewardShareMintingAddress(repository, this.minterPublicKey);
|
||||
} catch (DataException e) {
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
public int getMinterLevelFromPublicKey() {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
return Account.getRewardShareEffectiveMintingLevel(repository, this.minterPublicKey);
|
||||
} catch (DataException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// JAXB special
|
||||
|
||||
@XmlElement(name = "minterAddress")
|
||||
protected String getMinterAddress() {
|
||||
return Crypto.toAddress(this.minterPublicKey);
|
||||
return getMinterAddressFromPublicKey();
|
||||
}
|
||||
|
||||
@XmlElement(name = "minterLevel")
|
||||
protected int getMinterLevel() {
|
||||
return getMinterLevelFromPublicKey();
|
||||
}
|
||||
}
|
||||
|
9
start.sh
9
start.sh
@ -33,8 +33,13 @@ fi
|
||||
# Limits Java JVM stack size and maximum heap usage.
|
||||
# Comment out for bigger systems, e.g. non-routers
|
||||
# or when API documentation is enabled
|
||||
# Uncomment (remove '#' sign) line below if your system has less than 12GB of RAM for optimal RAM defaults
|
||||
JVM_MEMORY_ARGS="-Xss256m -XX:+UseSerialGC"
|
||||
# JAVA MEMORY SETTINGS BELOW - These settings are essentially optimized default settings.
|
||||
# Combined with the latest changes on the Qortal Core in version 4.6.6 and beyond,
|
||||
# should give a dramatic increase In performance due to optimized Garbage Collection.
|
||||
# These memory arguments should work on machines with as little as 6GB of RAM.
|
||||
# If you want to run on a machine with less than 6GB of RAM, it is suggested to increase the '50' below to '75'
|
||||
# The Qortal Core will utilize only as much RAM as it needs, but up-to the amount set in percentage below.
|
||||
JVM_MEMORY_ARGS="-XX:MaxRAMPercentage=50 -XX:+UseG1GC -Xss1024k"
|
||||
|
||||
# Although java.net.preferIPv4Stack is supposed to be false
|
||||
# by default in Java 11, on some platforms (e.g. FreeBSD 12),
|
||||
|
Loading…
Reference in New Issue
Block a user