mirror of
https://github.com/Qortal/qortal.git
synced 2025-05-06 17:57:50 +00:00
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
@ -348,6 +348,24 @@ public class Account {
|
|||||||
return accountData.getLevel();
|
return accountData.getLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* Returns 'effective' minting level, or zero if reward-share does not exist.
|
||||||
*
|
*
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
package org.qortal.api.model;
|
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.XmlAccessType;
|
||||||
import javax.xml.bind.annotation.XmlAccessorType;
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
|
|
||||||
// All properties to be converted to JSON via JAXB
|
// All properties to be converted to JSON via JAXB
|
||||||
@XmlAccessorType(XmlAccessType.FIELD)
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
@ -47,4 +53,31 @@ public class ApiOnlineAccount {
|
|||||||
return this.recipientAddress;
|
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 class BlockMintingInfo {
|
||||||
|
|
||||||
public byte[] minterPublicKey;
|
public byte[] minterPublicKey;
|
||||||
|
public String minterAddress;
|
||||||
public int minterLevel;
|
public int minterLevel;
|
||||||
public int onlineAccountsCount;
|
public int onlineAccountsCount;
|
||||||
public BigDecimal maxDistance;
|
public BigDecimal maxDistance;
|
||||||
@ -19,5 +20,4 @@ public class BlockMintingInfo {
|
|||||||
|
|
||||||
public BlockMintingInfo() {
|
public BlockMintingInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -542,6 +542,7 @@ public class BlocksResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String minterAddress = Account.getRewardShareMintingAddress(repository, blockData.getMinterPublicKey());
|
||||||
int minterLevel = Account.getRewardShareEffectiveMintingLevel(repository, blockData.getMinterPublicKey());
|
int minterLevel = Account.getRewardShareEffectiveMintingLevel(repository, blockData.getMinterPublicKey());
|
||||||
if (minterLevel == 0)
|
if (minterLevel == 0)
|
||||||
// This may be unavailable when requesting a trimmed block
|
// This may be unavailable when requesting a trimmed block
|
||||||
@ -554,6 +555,7 @@ public class BlocksResource {
|
|||||||
|
|
||||||
BlockMintingInfo blockMintingInfo = new BlockMintingInfo();
|
BlockMintingInfo blockMintingInfo = new BlockMintingInfo();
|
||||||
blockMintingInfo.minterPublicKey = blockData.getMinterPublicKey();
|
blockMintingInfo.minterPublicKey = blockData.getMinterPublicKey();
|
||||||
|
blockMintingInfo.minterAddress = minterAddress;
|
||||||
blockMintingInfo.minterLevel = minterLevel;
|
blockMintingInfo.minterLevel = minterLevel;
|
||||||
blockMintingInfo.onlineAccountsCount = blockData.getOnlineAccountsCount();
|
blockMintingInfo.onlineAccountsCount = blockData.getOnlineAccountsCount();
|
||||||
blockMintingInfo.maxDistance = new BigDecimal(block.MAX_DISTANCE);
|
blockMintingInfo.maxDistance = new BigDecimal(block.MAX_DISTANCE);
|
||||||
@ -887,5 +889,4 @@ public class BlocksResource {
|
|||||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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()) {
|
if (onlineAccounts.isEmpty()) {
|
||||||
LOGGER.debug("No online accounts - not even our own?");
|
LOGGER.debug("No online accounts - not even our own?");
|
||||||
return null;
|
return null;
|
||||||
@ -721,19 +736,19 @@ public class Block {
|
|||||||
List<ExpandedAccount> expandedAccounts = new ArrayList<>();
|
List<ExpandedAccount> expandedAccounts = new ArrayList<>();
|
||||||
|
|
||||||
for (RewardShareData rewardShare : this.cachedOnlineRewardShares) {
|
for (RewardShareData rewardShare : this.cachedOnlineRewardShares) {
|
||||||
if (this.getBlockData().getHeight() < BlockChain.getInstance().getFixBatchRewardHeight()) {
|
int groupId = BlockChain.getInstance().getMintingGroupId();
|
||||||
expandedAccounts.add(new ExpandedAccount(repository, rewardShare));
|
String address = rewardShare.getMinter();
|
||||||
}
|
boolean isMinterGroupMember = repository.getGroupRepository().memberExists(groupId, address);
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
this.cachedExpandedAccounts = expandedAccounts;
|
this.cachedExpandedAccounts = expandedAccounts;
|
||||||
|
LOGGER.trace(() -> String.format("Online reward-shares after expanded accounts %s", this.cachedOnlineRewardShares));
|
||||||
|
|
||||||
return this.cachedExpandedAccounts;
|
return this.cachedExpandedAccounts;
|
||||||
}
|
}
|
||||||
@ -1143,8 +1158,17 @@ public class Block {
|
|||||||
if (this.getBlockData().getHeight() >= BlockChain.getInstance().getOnlineAccountMinterLevelValidationHeight()) {
|
if (this.getBlockData().getHeight() >= BlockChain.getInstance().getOnlineAccountMinterLevelValidationHeight()) {
|
||||||
List<ExpandedAccount> expandedAccounts = this.getExpandedAccounts();
|
List<ExpandedAccount> expandedAccounts = this.getExpandedAccounts();
|
||||||
for (ExpandedAccount account : expandedAccounts) {
|
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)
|
if (account.getMintingAccount().getEffectiveMintingLevel() == 0)
|
||||||
return ValidationResult.ONLINE_ACCOUNTS_INVALID;
|
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
|
// Online Accounts
|
||||||
ValidationResult onlineAccountsResult = this.areOnlineAccountsValid();
|
ValidationResult onlineAccountsResult = this.areOnlineAccountsValid();
|
||||||
|
LOGGER.trace("Accounts valid = {}", onlineAccountsResult);
|
||||||
if (onlineAccountsResult != ValidationResult.OK)
|
if (onlineAccountsResult != ValidationResult.OK)
|
||||||
return onlineAccountsResult;
|
return onlineAccountsResult;
|
||||||
|
|
||||||
@ -1361,7 +1386,7 @@ public class Block {
|
|||||||
// Check transaction can even be processed
|
// Check transaction can even be processed
|
||||||
validationResult = transaction.isProcessable();
|
validationResult = transaction.isProcessable();
|
||||||
if (validationResult != Transaction.ValidationResult.OK) {
|
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;
|
return ValidationResult.TRANSACTION_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1562,6 +1587,7 @@ public class Block {
|
|||||||
this.blockData.setHeight(blockchainHeight + 1);
|
this.blockData.setHeight(blockchainHeight + 1);
|
||||||
|
|
||||||
LOGGER.trace(() -> String.format("Processing block %d", this.blockData.getHeight()));
|
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) {
|
if (this.blockData.getHeight() > 1) {
|
||||||
|
|
||||||
@ -2280,7 +2306,6 @@ public class Block {
|
|||||||
// Select the correct set of share bins based on block height
|
// Select the correct set of share bins based on block height
|
||||||
List<AccountLevelShareBin> accountLevelShareBinsForBlock = (this.blockData.getHeight() >= BlockChain.getInstance().getSharesByLevelV2Height()) ?
|
List<AccountLevelShareBin> accountLevelShareBinsForBlock = (this.blockData.getHeight() >= BlockChain.getInstance().getSharesByLevelV2Height()) ?
|
||||||
BlockChain.getInstance().getAccountLevelShareBinsV2() : BlockChain.getInstance().getAccountLevelShareBinsV1();
|
BlockChain.getInstance().getAccountLevelShareBinsV2() : BlockChain.getInstance().getAccountLevelShareBinsV1();
|
||||||
|
|
||||||
// Determine reward candidates based on account level
|
// Determine reward candidates based on account level
|
||||||
// This needs a deep copy, so the shares can be modified when tiers aren't activated yet
|
// This needs a deep copy, so the shares can be modified when tiers aren't activated yet
|
||||||
List<AccountLevelShareBin> accountLevelShareBins = new ArrayList<>();
|
List<AccountLevelShareBin> accountLevelShareBins = new ArrayList<>();
|
||||||
@ -2570,9 +2595,11 @@ public class Block {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
int minterLevel = Account.getRewardShareEffectiveMintingLevel(this.repository, this.getMinter().getPublicKey());
|
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("======= BLOCK %d (%.8s) =======", this.getBlockData().getHeight(), Base58.encode(this.getSignature())));
|
||||||
LOGGER.debug(String.format("Timestamp: %d", this.getBlockData().getTimestamp()));
|
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("Minter level: %d", minterLevel));
|
||||||
LOGGER.debug(String.format("Online accounts: %d", this.getBlockData().getOnlineAccountsCount()));
|
LOGGER.debug(String.format("Online accounts: %d", this.getBlockData().getOnlineAccountsCount()));
|
||||||
LOGGER.debug(String.format("AT count: %d", this.getBlockData().getATCount()));
|
LOGGER.debug(String.format("AT count: %d", this.getBlockData().getATCount()));
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
package org.qortal.data.block;
|
package org.qortal.data.block;
|
||||||
|
|
||||||
import com.google.common.primitives.Bytes;
|
import com.google.common.primitives.Bytes;
|
||||||
|
import org.qortal.account.Account;
|
||||||
import org.qortal.block.BlockChain;
|
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.settings.Settings;
|
||||||
import org.qortal.utils.NTP;
|
import org.qortal.utils.NTP;
|
||||||
|
|
||||||
@ -232,11 +235,31 @@ public class BlockData implements Serializable {
|
|||||||
return blockTimestamp < onlineAccountSignaturesTrimmedTimestamp && blockTimestamp < currentTrimmableTimestamp;
|
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
|
// JAXB special
|
||||||
|
|
||||||
@XmlElement(name = "minterAddress")
|
@XmlElement(name = "minterAddress")
|
||||||
protected String getMinterAddress() {
|
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.
|
# Limits Java JVM stack size and maximum heap usage.
|
||||||
# Comment out for bigger systems, e.g. non-routers
|
# Comment out for bigger systems, e.g. non-routers
|
||||||
# or when API documentation is enabled
|
# or when API documentation is enabled
|
||||||
# Uncomment (remove '#' sign) line below if your system has less than 12GB of RAM for optimal RAM defaults
|
# JAVA MEMORY SETTINGS BELOW - These settings are essentially optimized default settings.
|
||||||
JVM_MEMORY_ARGS="-Xss256m -XX:+UseSerialGC"
|
# 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
|
# Although java.net.preferIPv4Stack is supposed to be false
|
||||||
# by default in Java 11, on some platforms (e.g. FreeBSD 12),
|
# by default in Java 11, on some platforms (e.g. FreeBSD 12),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user