mirror of
https://github.com/Qortal/qortal.git
synced 2025-07-30 21:51:26 +00:00
Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4824c4198b | ||
|
ec7d4f4498 | ||
|
d635de44a8 | ||
|
bce66bf57f | ||
|
0fc5153f9b | ||
|
0398c2fae1 | ||
|
5fc495eb6a | ||
|
7918622e2e | ||
|
427fa1816d | ||
|
0c7e388463 | ||
|
be3af53011 | ||
|
414399b2a0 | ||
|
c592051a80 | ||
|
33a8f311e5 | ||
|
018c3cdcd4 | ||
|
384dffbf9a | ||
|
0306ecb03d | ||
|
e5ce732557 | ||
|
91925cf931 |
@@ -2,6 +2,7 @@
|
||||
|
||||
## TL;DR: how-to
|
||||
|
||||
* Prepare new release version (see way below for details)
|
||||
* Assuming you are in git 'master' branch, at HEAD
|
||||
* Shutdown local node if running
|
||||
* Build auto-update download: `tools/build-auto-update.sh` - uploads auto-update file into new git branch
|
||||
@@ -59,4 +60,12 @@ $ java -cp qortal.jar org.qortal.XorUpdate
|
||||
usage: XorUpdate <input-file> <output-file>
|
||||
$ java -cp qortal.jar org.qortal.XorUpdate qortal.jar qortal.update
|
||||
$
|
||||
```
|
||||
```
|
||||
|
||||
## Preparing new release version
|
||||
|
||||
* Shutdown local node
|
||||
* Modify `pom.xml` and increase version inside `<version>` tag
|
||||
* Commit new `pom.xml` and push to github, e.g. `git commit -m 'Bumped to v1.4.2' -- pom.xml; git push`
|
||||
* Tag this new commit with same version: `git tag v1.4.2`
|
||||
* Push tag up to github: `git push origin v1.4.2`
|
||||
|
Binary file not shown.
@@ -19,10 +19,10 @@
|
||||
<ROW Property="Manufacturer" Value="Qortal"/>
|
||||
<ROW Property="MsiLogging" MultiBuildValue="DefaultBuild:vp"/>
|
||||
<ROW Property="NTP_GOOD" Value="false"/>
|
||||
<ROW Property="ProductCode" Value="1033:{9BC18BE1-7E1F-4103-9B2B-EC26CF4CE974} 1049:{6DD00C11-C69C-49FD-BCAF-BE2F0A7175AA} 2052:{9898B095-DAA0-49D5-B190-0B9A14C80E90} 2057:{FAD15601-2960-4759-9CF4-047B69FF6D17} " Type="16"/>
|
||||
<ROW Property="ProductCode" Value="1033:{9EA6B58D-641E-442E-8F16-5D35B92B9F9B} 1049:{B16722F6-C2FA-418D-A9DA-69707FE2034B} 2052:{459AC873-98DC-43AC-8787-B23BAF976FF5} 2057:{CD923B63-65A0-4F2A-93B6-6362AAC8608E} " Type="16"/>
|
||||
<ROW Property="ProductLanguage" Value="2057"/>
|
||||
<ROW Property="ProductName" Value="Qortal"/>
|
||||
<ROW Property="ProductVersion" Value="1.4.1" Type="32"/>
|
||||
<ROW Property="ProductVersion" Value="1.4.2" Type="32"/>
|
||||
<ROW Property="RECONFIG_NTP" Value="true"/>
|
||||
<ROW Property="REMOVE_BLOCKCHAIN" Value="YES" Type="4"/>
|
||||
<ROW Property="REPAIR_BLOCKCHAIN" Value="YES" Type="4"/>
|
||||
@@ -174,7 +174,7 @@
|
||||
<ROW Component="ADDITIONAL_LICENSE_INFO_97" ComponentId="{D5544706-E2A7-424F-AEA5-3963E355AA29}" Directory_="jdk.crypto.mscapi_Dir" Attributes="0" KeyPath="ADDITIONAL_LICENSE_INFO_97" Type="0"/>
|
||||
<ROW Component="ADDITIONAL_LICENSE_INFO_98" ComponentId="{104DBCE8-A458-4B3E-9EFA-2D8613561619}" Directory_="jdk.dynalink_Dir" Attributes="0" KeyPath="ADDITIONAL_LICENSE_INFO_98" Type="0"/>
|
||||
<ROW Component="ADDITIONAL_LICENSE_INFO_99" ComponentId="{D02E3C37-E81A-48FA-9E28-B26B728AECD9}" Directory_="jdk.httpserver_Dir" Attributes="0" KeyPath="ADDITIONAL_LICENSE_INFO_99" Type="0"/>
|
||||
<ROW Component="AI_CustomARPName" ComponentId="{23EC1B2A-D6F8-459B-B5CA-6974919022A6}" Directory_="APPDIR" Attributes="260" KeyPath="DisplayName" Options="1"/>
|
||||
<ROW Component="AI_CustomARPName" ComponentId="{F9375D31-26C0-4E23-948D-3570B43B7FA2}" Directory_="APPDIR" Attributes="260" KeyPath="DisplayName" Options="1"/>
|
||||
<ROW Component="AI_ExePath" ComponentId="{3644948D-AE0B-41BB-9FAF-A79E70490A08}" Directory_="APPDIR" Attributes="260" KeyPath="AI_ExePath"/>
|
||||
<ROW Component="APPDIR" ComponentId="{680DFDDE-3FB4-47A5-8FF5-934F576C6F91}" Directory_="APPDIR" Attributes="0"/>
|
||||
<ROW Component="DATA_PATH" ComponentId="{EE0B6107-E244-4CDB-B195-E9038D2F1E0E}" Directory_="DATA_PATH" Attributes="0"/>
|
||||
|
2
pom.xml
2
pom.xml
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.qortal</groupId>
|
||||
<artifactId>qortal</artifactId>
|
||||
<version>1.4.2</version>
|
||||
<version>1.4.4</version>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<skipTests>true</skipTests>
|
||||
|
@@ -357,7 +357,7 @@ public class Block {
|
||||
System.arraycopy(onlineAccountData.getSignature(), 0, onlineAccountsSignatures, i * Transformer.SIGNATURE_LENGTH, Transformer.SIGNATURE_LENGTH);
|
||||
}
|
||||
|
||||
byte[] minterSignature = minter.sign(BlockTransformer.getBytesForMinterSignature(parentBlockData.getMinterSignature(),
|
||||
byte[] minterSignature = minter.sign(BlockTransformer.getBytesForMinterSignature(parentBlockData,
|
||||
minter.getPublicKey(), encodedOnlineAccounts));
|
||||
|
||||
// Qortal: minter is always a reward-share, so find actual minter and get their effective minting level
|
||||
@@ -424,7 +424,7 @@ public class Block {
|
||||
int version = this.blockData.getVersion();
|
||||
byte[] reference = this.blockData.getReference();
|
||||
|
||||
byte[] minterSignature = minter.sign(BlockTransformer.getBytesForMinterSignature(parentBlockData.getMinterSignature(),
|
||||
byte[] minterSignature = minter.sign(BlockTransformer.getBytesForMinterSignature(parentBlockData,
|
||||
minter.getPublicKey(), this.blockData.getEncodedOnlineAccounts()));
|
||||
|
||||
// Qortal: minter is always a reward-share, so find actual minter and get their effective minting level
|
||||
@@ -738,11 +738,7 @@ public class Block {
|
||||
if (!(this.minter instanceof PrivateKeyAccount))
|
||||
throw new IllegalStateException("Block's minter is not a PrivateKeyAccount - can't sign!");
|
||||
|
||||
try {
|
||||
this.blockData.setMinterSignature(((PrivateKeyAccount) this.minter).sign(BlockTransformer.getBytesForMinterSignature(this.blockData)));
|
||||
} catch (TransformationException e) {
|
||||
throw new RuntimeException("Unable to calculate block's minter signature", e);
|
||||
}
|
||||
this.blockData.setMinterSignature(((PrivateKeyAccount) this.minter).sign(BlockTransformer.getBytesForMinterSignature(this.blockData)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -70,7 +70,8 @@ public class BlockChain {
|
||||
private GenesisBlock.GenesisInfo genesisInfo;
|
||||
|
||||
public enum FeatureTrigger {
|
||||
atFindNextTransactionFix;
|
||||
atFindNextTransactionFix,
|
||||
newBlockSigHeight;
|
||||
}
|
||||
|
||||
/** Map of which blockchain features are enabled when (height/timestamp) */
|
||||
@@ -376,6 +377,10 @@ public class BlockChain {
|
||||
return this.featureTriggers.get(FeatureTrigger.atFindNextTransactionFix.name()).intValue();
|
||||
}
|
||||
|
||||
public int getNewBlockSigHeight() {
|
||||
return this.featureTriggers.get(FeatureTrigger.newBlockSigHeight.name()).intValue();
|
||||
}
|
||||
|
||||
// More complex getters for aspects that change by height or timestamp
|
||||
|
||||
public long getRewardAtHeight(int ourHeight) {
|
||||
|
@@ -143,7 +143,6 @@ public class Controller extends Thread {
|
||||
private ExecutorService callbackExecutor = Executors.newFixedThreadPool(3);
|
||||
private volatile boolean notifyGroupMembershipChange = false;
|
||||
|
||||
private static final int BLOCK_CACHE_SIZE = 10; // To cover typical Synchronizer request + a few spare
|
||||
/** Latest blocks on our chain. Note: tail/last is the latest block. */
|
||||
private final Deque<BlockData> latestBlocks = new LinkedList<>();
|
||||
|
||||
@@ -152,7 +151,7 @@ public class Controller extends Thread {
|
||||
private final LinkedHashMap<ByteArray, BlockMessage> blockMessageCache = new LinkedHashMap<>() {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<ByteArray, BlockMessage> eldest) {
|
||||
return this.size() > BLOCK_CACHE_SIZE;
|
||||
return this.size() > Settings.getInstance().getBlockCacheSize();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -319,11 +318,12 @@ public class Controller extends Thread {
|
||||
// Set initial chain height/tip
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
BlockData blockData = repository.getBlockRepository().getLastBlock();
|
||||
int blockCacheSize = Settings.getInstance().getBlockCacheSize();
|
||||
|
||||
synchronized (this.latestBlocks) {
|
||||
this.latestBlocks.clear();
|
||||
|
||||
for (int i = 0; i < BLOCK_CACHE_SIZE && blockData != null; ++i) {
|
||||
for (int i = 0; i < blockCacheSize && blockData != null; ++i) {
|
||||
this.latestBlocks.addFirst(blockData);
|
||||
blockData = repository.getBlockRepository().fromHeight(blockData.getHeight() - 1);
|
||||
}
|
||||
@@ -933,6 +933,7 @@ public class Controller extends Thread {
|
||||
public void onNewBlock(BlockData latestBlockData) {
|
||||
// Protective copy
|
||||
BlockData blockDataCopy = new BlockData(latestBlockData);
|
||||
int blockCacheSize = Settings.getInstance().getBlockCacheSize();
|
||||
|
||||
synchronized (this.latestBlocks) {
|
||||
BlockData cachedChainTip = this.latestBlocks.peekLast();
|
||||
@@ -942,7 +943,7 @@ public class Controller extends Thread {
|
||||
this.latestBlocks.addLast(latestBlockData);
|
||||
|
||||
// Trim if necessary
|
||||
if (this.latestBlocks.size() >= BLOCK_CACHE_SIZE)
|
||||
if (this.latestBlocks.size() >= blockCacheSize)
|
||||
this.latestBlocks.pollFirst();
|
||||
} else {
|
||||
if (cachedChainTip != null)
|
||||
@@ -1151,6 +1152,7 @@ public class Controller extends Thread {
|
||||
ByteArray signatureAsByteArray = new ByteArray(signature);
|
||||
|
||||
BlockMessage cachedBlockMessage = this.blockMessageCache.get(signatureAsByteArray);
|
||||
int blockCacheSize = Settings.getInstance().getBlockCacheSize();
|
||||
|
||||
// Check cached latest block message
|
||||
if (cachedBlockMessage != null) {
|
||||
@@ -1193,7 +1195,7 @@ public class Controller extends Thread {
|
||||
peer.disconnect("failed to send block");
|
||||
|
||||
// If request is for a recent block, cache it
|
||||
if (getChainHeight() - blockData.getHeight() <= BLOCK_CACHE_SIZE) {
|
||||
if (getChainHeight() - blockData.getHeight() <= blockCacheSize) {
|
||||
this.stats.getBlockMessageStats.cacheFills.incrementAndGet();
|
||||
|
||||
this.blockMessageCache.put(new ByteArray(blockData.getSignature()), blockMessage);
|
||||
@@ -1207,6 +1209,18 @@ public class Controller extends Thread {
|
||||
TransactionMessage transactionMessage = (TransactionMessage) message;
|
||||
TransactionData transactionData = transactionMessage.getTransactionData();
|
||||
|
||||
/*
|
||||
* If we can't obtain blockchain lock immediately,
|
||||
* e.g. Synchronizer is active, or another transaction is taking a while to validate,
|
||||
* then we're using up a network thread for ages and clogging things up
|
||||
* so bail out early
|
||||
*/
|
||||
ReentrantLock blockchainLock = Controller.getInstance().getBlockchainLock();
|
||||
if (!blockchainLock.tryLock()) {
|
||||
LOGGER.trace(() -> String.format("Too busy to import %s transaction %s from peer %s", transactionData.getType().name(), Base58.encode(transactionData.getSignature()), peer));
|
||||
return;
|
||||
}
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
Transaction transaction = Transaction.fromData(repository, transactionData);
|
||||
|
||||
@@ -1236,6 +1250,8 @@ public class Controller extends Thread {
|
||||
LOGGER.debug(() -> String.format("Imported %s transaction %s from peer %s", transactionData.getType().name(), Base58.encode(transactionData.getSignature()), peer));
|
||||
} catch (DataException e) {
|
||||
LOGGER.error(String.format("Repository issue while processing transaction %s from peer %s", Base58.encode(transactionData.getSignature()), peer), e);
|
||||
} finally {
|
||||
blockchainLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -23,7 +23,7 @@ public interface AcctTradeBot {
|
||||
public ResponseResult startResponse(Repository repository, ATData atData, ACCT acct,
|
||||
CrossChainTradeData crossChainTradeData, String foreignKey, String receivingAddress) throws DataException;
|
||||
|
||||
public boolean canDelete(Repository repository, TradeBotData tradeBotData);
|
||||
public boolean canDelete(Repository repository, TradeBotData tradeBotData) throws DataException;
|
||||
|
||||
public void progress(Repository repository, TradeBotData tradeBotData) throws DataException, ForeignBlockchainException;
|
||||
|
||||
|
@@ -345,11 +345,15 @@ public class BitcoinACCTv1TradeBot implements AcctTradeBot {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDelete(Repository repository, TradeBotData tradeBotData) {
|
||||
public boolean canDelete(Repository repository, TradeBotData tradeBotData) throws DataException {
|
||||
State tradeBotState = State.valueOf(tradeBotData.getStateValue());
|
||||
if (tradeBotState == null)
|
||||
return true;
|
||||
|
||||
// If the AT doesn't exist then we might as well let the user tidy up
|
||||
if (!repository.getATRepository().exists(tradeBotData.getAtAddress()))
|
||||
return true;
|
||||
|
||||
switch (tradeBotState) {
|
||||
case BOB_WAITING_FOR_AT_CONFIRM:
|
||||
case ALICE_DONE:
|
||||
@@ -378,7 +382,16 @@ public class BitcoinACCTv1TradeBot implements AcctTradeBot {
|
||||
// Attempt to fetch AT data
|
||||
atData = repository.getATRepository().fromATAddress(tradeBotData.getAtAddress());
|
||||
if (atData == null) {
|
||||
LOGGER.warn(() -> String.format("Unable to fetch trade AT %s from repository", tradeBotData.getAtAddress()));
|
||||
LOGGER.debug(() -> String.format("Unable to fetch trade AT %s from repository", tradeBotData.getAtAddress()));
|
||||
|
||||
// If it has been over 24 hours since we last updated this trade-bot entry then assume AT is never coming back
|
||||
// and so wipe the trade-bot entry
|
||||
if (tradeBotData.getTimestamp() + MAX_AT_CONFIRMATION_PERIOD < NTP.getTime()) {
|
||||
LOGGER.info(() -> String.format("AT %s has been gone for too long - deleting trade-bot entry", tradeBotData.getAtAddress()));
|
||||
repository.getCrossChainRepository().delete(tradeBotData.getTradePrivateKey());
|
||||
repository.saveChanges();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -343,11 +343,15 @@ public class LitecoinACCTv1TradeBot implements AcctTradeBot {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDelete(Repository repository, TradeBotData tradeBotData) {
|
||||
public boolean canDelete(Repository repository, TradeBotData tradeBotData) throws DataException {
|
||||
State tradeBotState = State.valueOf(tradeBotData.getStateValue());
|
||||
if (tradeBotState == null)
|
||||
return true;
|
||||
|
||||
// If the AT doesn't exist then we might as well let the user tidy up
|
||||
if (!repository.getATRepository().exists(tradeBotData.getAtAddress()))
|
||||
return true;
|
||||
|
||||
switch (tradeBotState) {
|
||||
case BOB_WAITING_FOR_AT_CONFIRM:
|
||||
case ALICE_DONE:
|
||||
@@ -376,7 +380,16 @@ public class LitecoinACCTv1TradeBot implements AcctTradeBot {
|
||||
// Attempt to fetch AT data
|
||||
atData = repository.getATRepository().fromATAddress(tradeBotData.getAtAddress());
|
||||
if (atData == null) {
|
||||
LOGGER.warn(() -> String.format("Unable to fetch trade AT %s from repository", tradeBotData.getAtAddress()));
|
||||
LOGGER.debug(() -> String.format("Unable to fetch trade AT %s from repository", tradeBotData.getAtAddress()));
|
||||
|
||||
// If it has been over 24 hours since we last updated this trade-bot entry then assume AT is never coming back
|
||||
// and so wipe the trade-bot entry
|
||||
if (tradeBotData.getTimestamp() + MAX_AT_CONFIRMATION_PERIOD < NTP.getTime()) {
|
||||
LOGGER.info(() -> String.format("AT %s has been gone for too long - deleting trade-bot entry", tradeBotData.getAtAddress()));
|
||||
repository.getCrossChainRepository().delete(tradeBotData.getTradePrivateKey());
|
||||
repository.saveChanges();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package org.qortal.repository;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -251,6 +252,14 @@ public interface TransactionRepository {
|
||||
*/
|
||||
public List<TransactionData> getUnconfirmedTransactions(TransactionType txType, byte[] creatorPublicKey) throws DataException;
|
||||
|
||||
/**
|
||||
* Returns list of unconfirmed transactions excluding specified type(s).
|
||||
*
|
||||
* @return list of transactions, or empty if none.
|
||||
* @throws DataException
|
||||
*/
|
||||
public List<TransactionData> getUnconfirmedTransactions(EnumSet<TransactionType> excludedTxTypes) throws DataException;
|
||||
|
||||
/**
|
||||
* Remove transaction from unconfirmed transactions pile.
|
||||
*
|
||||
|
@@ -931,6 +931,8 @@ public class HSQLDBRepository implements Repository {
|
||||
|
||||
/** Logs other HSQLDB sessions then returns passed exception */
|
||||
public SQLException examineException(SQLException e) {
|
||||
// TODO: could log at DEBUG for deadlocks by checking RepositoryManager.isDeadlockRelated(e)?
|
||||
|
||||
LOGGER.error(() -> String.format("[Session %d] HSQLDB error: %s", this.sessionId, e.getMessage()), e);
|
||||
|
||||
logStatements();
|
||||
|
@@ -14,11 +14,11 @@ import org.hsqldb.jdbc.HSQLDBPool;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
import org.qortal.repository.RepositoryFactory;
|
||||
import org.qortal.settings.Settings;
|
||||
|
||||
public class HSQLDBRepositoryFactory implements RepositoryFactory {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(HSQLDBRepositoryFactory.class);
|
||||
private static final int POOL_SIZE = 100;
|
||||
|
||||
/** Log getConnection() calls that take longer than this. (ms) */
|
||||
private static final long SLOW_CONNECTION_THRESHOLD = 1000L;
|
||||
@@ -57,7 +57,7 @@ public class HSQLDBRepositoryFactory implements RepositoryFactory {
|
||||
HSQLDBRepository.attemptRecovery(connectionUrl);
|
||||
}
|
||||
|
||||
this.connectionPool = new HSQLDBPool(POOL_SIZE);
|
||||
this.connectionPool = new HSQLDBPool(Settings.getInstance().getRepositoryConnectionPoolSize());
|
||||
this.connectionPool.setUrl(this.connectionUrl);
|
||||
|
||||
Properties properties = new Properties();
|
||||
|
@@ -9,6 +9,7 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -1181,6 +1182,51 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TransactionData> getUnconfirmedTransactions(EnumSet<TransactionType> excludedTxTypes) throws DataException {
|
||||
StringBuilder sql = new StringBuilder(1024);
|
||||
sql.append("SELECT signature FROM UnconfirmedTransactions ");
|
||||
sql.append("JOIN Transactions USING (signature) ");
|
||||
sql.append("WHERE type NOT IN (");
|
||||
|
||||
boolean firstTxType = true;
|
||||
for (TransactionType txType : excludedTxTypes) {
|
||||
if (firstTxType)
|
||||
firstTxType = false;
|
||||
else
|
||||
sql.append(", ");
|
||||
|
||||
sql.append(txType.value);
|
||||
}
|
||||
|
||||
sql.append(")");
|
||||
sql.append("ORDER BY created_when, signature");
|
||||
|
||||
List<TransactionData> transactions = new ArrayList<>();
|
||||
|
||||
// Find transactions with no corresponding row in BlockTransactions
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql.toString())) {
|
||||
if (resultSet == null)
|
||||
return transactions;
|
||||
|
||||
do {
|
||||
byte[] signature = resultSet.getBytes(1);
|
||||
|
||||
TransactionData transactionData = this.fromSignature(signature);
|
||||
|
||||
if (transactionData == null)
|
||||
// Something inconsistent with the repository
|
||||
throw new DataException(String.format("Unable to fetch unconfirmed transaction %s from repository?", Base58.encode(signature)));
|
||||
|
||||
transactions.add(transactionData);
|
||||
} while (resultSet.next());
|
||||
|
||||
return transactions;
|
||||
} catch (SQLException | DataException e) {
|
||||
throw new DataException("Unable to fetch unconfirmed transactions from repository", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void confirmTransaction(byte[] signature) throws DataException {
|
||||
try {
|
||||
|
@@ -89,6 +89,8 @@ public class Settings {
|
||||
private long repositoryCheckpointInterval = 60 * 60 * 1000L; // 1 hour (ms) default
|
||||
/** Whether to show a notification when we perform repository 'checkpoint'. */
|
||||
private boolean showCheckpointNotification = false;
|
||||
/* How many blocks to cache locally. Defaulted to 10, which covers a typical Synchronizer request + a few spare */
|
||||
private int blockCacheSize = 10;
|
||||
|
||||
/** How long to keep old, full, AT state data (ms). */
|
||||
private long atStatesMaxLifetime = 2 * 7 * 24 * 60 * 60 * 1000L; // milliseconds
|
||||
@@ -134,6 +136,8 @@ public class Settings {
|
||||
private Long slowQueryThreshold = null;
|
||||
/** Repository storage path. */
|
||||
private String repositoryPath = "db";
|
||||
/** Repository connection pool size. Needs to be a bit bigger than maxNetworkThreadPoolSize */
|
||||
private int repositoryConnectionPoolSize = 100;
|
||||
|
||||
// Auto-update sources
|
||||
private String[] autoUpdateRepos = new String[] {
|
||||
@@ -361,6 +365,10 @@ public class Settings {
|
||||
return this.maxTransactionTimestampFuture;
|
||||
}
|
||||
|
||||
public int getBlockCacheSize() {
|
||||
return this.blockCacheSize;
|
||||
}
|
||||
|
||||
public boolean isTestNet() {
|
||||
return this.isTestNet;
|
||||
}
|
||||
@@ -424,6 +432,10 @@ public class Settings {
|
||||
return this.repositoryPath;
|
||||
}
|
||||
|
||||
public int getRepositoryConnectionPoolSize() {
|
||||
return this.repositoryConnectionPoolSize;
|
||||
}
|
||||
|
||||
public boolean isAutoUpdateEnabled() {
|
||||
return this.autoUpdateEnabled;
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -605,7 +606,8 @@ public abstract class Transaction {
|
||||
public static List<TransactionData> getUnconfirmedTransactions(Repository repository) throws DataException {
|
||||
BlockData latestBlockData = repository.getBlockRepository().getLastBlock();
|
||||
|
||||
List<TransactionData> unconfirmedTransactions = repository.getTransactionRepository().getUnconfirmedTransactions();
|
||||
EnumSet<TransactionType> excludedTxTypes = EnumSet.of(TransactionType.CHAT, TransactionType.PRESENCE);
|
||||
List<TransactionData> unconfirmedTransactions = repository.getTransactionRepository().getUnconfirmedTransactions(excludedTxTypes);
|
||||
|
||||
unconfirmedTransactions.sort(getDataComparator());
|
||||
|
||||
|
@@ -326,24 +326,36 @@ public class BlockTransformer extends Transformer {
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] getMinterSignatureFromReference(byte[] blockReference) {
|
||||
return Arrays.copyOf(blockReference, MINTER_SIGNATURE_LENGTH);
|
||||
private static byte[] getReferenceBytesForMinterSignature(int blockHeight, byte[] reference) {
|
||||
int newBlockSigTriggerHeight = BlockChain.getInstance().getNewBlockSigHeight();
|
||||
|
||||
return blockHeight >= newBlockSigTriggerHeight
|
||||
// 'new' block sig uses all of previous block's signature
|
||||
? reference
|
||||
// 'old' block sig only uses first 64 bytes of previous block's signature
|
||||
: Arrays.copyOf(reference, MINTER_SIGNATURE_LENGTH);
|
||||
}
|
||||
|
||||
public static byte[] getBytesForMinterSignature(BlockData blockData) throws TransformationException {
|
||||
byte[] minterSignature = getMinterSignatureFromReference(blockData.getReference());
|
||||
public static byte[] getBytesForMinterSignature(BlockData blockData) {
|
||||
byte[] referenceBytes = getReferenceBytesForMinterSignature(blockData.getHeight(), blockData.getReference());
|
||||
|
||||
return getBytesForMinterSignature(minterSignature, blockData.getMinterPublicKey(), blockData.getEncodedOnlineAccounts());
|
||||
return getBytesForMinterSignature(referenceBytes, blockData.getMinterPublicKey(), blockData.getEncodedOnlineAccounts());
|
||||
}
|
||||
|
||||
public static byte[] getBytesForMinterSignature(byte[] minterSignature, byte[] minterPublicKey, byte[] encodedOnlineAccounts) {
|
||||
byte[] bytes = new byte[MINTER_SIGNATURE_LENGTH + MINTER_PUBLIC_KEY_LENGTH + encodedOnlineAccounts.length];
|
||||
public static byte[] getBytesForMinterSignature(BlockData parentBlockData, byte[] minterPublicKey, byte[] encodedOnlineAccounts) {
|
||||
byte[] referenceBytes = getReferenceBytesForMinterSignature(parentBlockData.getHeight() + 1, parentBlockData.getSignature());
|
||||
|
||||
System.arraycopy(minterSignature, 0, bytes, 0, MINTER_SIGNATURE_LENGTH);
|
||||
return getBytesForMinterSignature(referenceBytes, minterPublicKey, encodedOnlineAccounts);
|
||||
}
|
||||
|
||||
System.arraycopy(minterPublicKey, 0, bytes, MINTER_SIGNATURE_LENGTH, MINTER_PUBLIC_KEY_LENGTH);
|
||||
private static byte[] getBytesForMinterSignature(byte[] referenceBytes, byte[] minterPublicKey, byte[] encodedOnlineAccounts) {
|
||||
byte[] bytes = new byte[referenceBytes.length + MINTER_PUBLIC_KEY_LENGTH + encodedOnlineAccounts.length];
|
||||
|
||||
System.arraycopy(encodedOnlineAccounts, 0, bytes, MINTER_SIGNATURE_LENGTH + MINTER_PUBLIC_KEY_LENGTH, encodedOnlineAccounts.length);
|
||||
System.arraycopy(referenceBytes, 0, bytes, 0, referenceBytes.length);
|
||||
|
||||
System.arraycopy(minterPublicKey, 0, bytes, referenceBytes.length, MINTER_PUBLIC_KEY_LENGTH);
|
||||
|
||||
System.arraycopy(encodedOnlineAccounts, 0, bytes, referenceBytes.length + MINTER_PUBLIC_KEY_LENGTH, encodedOnlineAccounts.length);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
@@ -48,7 +48,8 @@
|
||||
"minutesPerBlock": 1
|
||||
},
|
||||
"featureTriggers": {
|
||||
"atFindNextTransactionFix": 275000
|
||||
"atFindNextTransactionFix": 275000,
|
||||
"newBlockSigHeight": 320000
|
||||
},
|
||||
"genesisInfo": {
|
||||
"version": 4,
|
||||
|
72
src/main/resources/i18n/ApiError_it.properties
Normal file
72
src/main/resources/i18n/ApiError_it.properties
Normal file
@@ -0,0 +1,72 @@
|
||||
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
|
||||
# Keys are from api.ApiError enum
|
||||
# Italian translation by Pabs 2021
|
||||
|
||||
# La modifica della lingua dell'UI è fatta nel file Settings.json
|
||||
#
|
||||
# "localeLang": "it",
|
||||
# Si prega ricordare la virgola alla fine, se questo comando non è sull'ultima riga
|
||||
|
||||
ADDRESS_UNKNOWN = indirizzo account sconosciuto
|
||||
|
||||
BLOCKCHAIN_NEEDS_SYNC = blockchain deve prima sincronizzarsi
|
||||
|
||||
# Blocks
|
||||
BLOCK_UNKNOWN = blocco sconosciuto
|
||||
|
||||
BTC_BALANCE_ISSUE = saldo Bitcoin insufficiente
|
||||
|
||||
BTC_NETWORK_ISSUE = Bitcoin/ElectrumX problema di rete
|
||||
|
||||
BTC_TOO_SOON = troppo presto per trasmettere transazione Bitcoin (tempo di blocco / tempo di blocco mediano)
|
||||
|
||||
CANNOT_MINT = l'account non può coniare
|
||||
|
||||
GROUP_UNKNOWN = gruppo sconosciuto
|
||||
|
||||
INVALID_ADDRESS = indirizzo non valido
|
||||
|
||||
# Assets
|
||||
INVALID_ASSET_ID = identificazione risorsa non valida
|
||||
|
||||
INVALID_CRITERIA = criteri di ricerca non validi
|
||||
|
||||
INVALID_DATA = dati non validi
|
||||
|
||||
INVALID_HEIGHT = altezza blocco non valida
|
||||
|
||||
INVALID_NETWORK_ADDRESS = indirizzo di rete non valido
|
||||
|
||||
INVALID_ORDER_ID = identificazione di ordine di risorsa non valida
|
||||
|
||||
INVALID_PRIVATE_KEY = chiave privata non valida
|
||||
|
||||
INVALID_PUBLIC_KEY = chiave pubblica non valida
|
||||
|
||||
INVALID_REFERENCE = riferimento non valido
|
||||
|
||||
# Validation
|
||||
INVALID_SIGNATURE = firma non valida
|
||||
|
||||
JSON = Impossibile analizzare il messaggio JSON
|
||||
|
||||
NAME_UNKNOWN = nome sconosciuto
|
||||
|
||||
NON_PRODUCTION = questa chiamata API non è consentita per i sistemi di produzione
|
||||
|
||||
NO_TIME_SYNC = nessuna sincronizzazione dell'orologio ancora
|
||||
|
||||
ORDER_UNKNOWN = identificazione di ordine di risorsa sconosciuta
|
||||
|
||||
PUBLIC_KEY_NOT_FOUND = chiave pubblica non trovata
|
||||
|
||||
REPOSITORY_ISSUE = errore del repositorio
|
||||
|
||||
# This one is special in that caller expected to pass two additional strings, hence the two %s
|
||||
TRANSACTION_INVALID = transazione non valida: %s (%s)
|
||||
|
||||
TRANSACTION_UNKNOWN = transazione sconosciuta
|
||||
|
||||
TRANSFORMATION_ERROR = non è stato possibile trasformare JSON in transazione
|
||||
|
||||
UNAUTHORIZED = Chiamata API non autorizzata
|
46
src/main/resources/i18n/SysTray_it.properties
Normal file
46
src/main/resources/i18n/SysTray_it.properties
Normal file
@@ -0,0 +1,46 @@
|
||||
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
|
||||
# SysTray pop-up menu
|
||||
# Italian translation by Pabs 2021
|
||||
|
||||
APPLYING_UPDATE_AND_RESTARTING = Applicando aggiornamento automatico e riavviando...
|
||||
|
||||
AUTO_UPDATE = Aggiornamento automatico
|
||||
|
||||
BLOCK_HEIGHT = altezza
|
||||
|
||||
CHECK_TIME_ACCURACY = Controlla la precisione dell'ora
|
||||
|
||||
CONNECTING = Collegando
|
||||
|
||||
CONNECTION = connessione
|
||||
|
||||
CONNECTIONS = connessioni
|
||||
|
||||
CREATING_BACKUP_OF_DB_FILES = Creazione di backup dei file di database...
|
||||
|
||||
DB_BACKUP = Backup del database
|
||||
|
||||
DB_CHECKPOINT = Punto di controllo del database
|
||||
|
||||
EXIT = Uscita
|
||||
|
||||
MINTING_DISABLED = NON coniando
|
||||
|
||||
MINTING_ENABLED = \u2714 Coniando
|
||||
|
||||
# Nagging about lack of NTP time sync
|
||||
NTP_NAG_CAPTION = L'orologio del computer è impreciso!
|
||||
|
||||
NTP_NAG_TEXT_UNIX = Installare servizio NTP per ottenere un orologio preciso.
|
||||
|
||||
NTP_NAG_TEXT_WINDOWS = Seleziona "Sincronizza orologio" dal menu per correggere.
|
||||
|
||||
OPEN_UI = Apri UI
|
||||
|
||||
PERFORMING_DB_CHECKPOINT = Salvataggio delle modifiche al database non salvate...
|
||||
|
||||
SYNCHRONIZE_CLOCK = Sincronizza orologio
|
||||
|
||||
SYNCHRONIZING_BLOCKCHAIN = Sincronizzando
|
||||
|
||||
SYNCHRONIZING_CLOCK = Sincronizzando orologio
|
185
src/main/resources/i18n/TransactionValidity_it.properties
Normal file
185
src/main/resources/i18n/TransactionValidity_it.properties
Normal file
@@ -0,0 +1,185 @@
|
||||
# Italian translation by Pabs 2021
|
||||
|
||||
ACCOUNT_ALREADY_EXISTS = l'account gia esiste
|
||||
|
||||
ACCOUNT_CANNOT_REWARD_SHARE = l'account non può fare la condivisione di ricompensa
|
||||
|
||||
ALREADY_GROUP_ADMIN = è già amministratore del gruppo
|
||||
|
||||
ALREADY_GROUP_MEMBER = è già membro del gruppo
|
||||
|
||||
ALREADY_VOTED_FOR_THAT_OPTION = già votato per questa opzione
|
||||
|
||||
ASSET_ALREADY_EXISTS = risorsa già esistente
|
||||
|
||||
ASSET_DOES_NOT_EXIST = risorsa non esistente
|
||||
|
||||
ASSET_DOES_NOT_MATCH_AT = l'asset non corrisponde all'asset di AT
|
||||
|
||||
ASSET_NOT_SPENDABLE = la risorsa non è spendibile
|
||||
|
||||
AT_ALREADY_EXISTS = AT gia esiste
|
||||
|
||||
AT_IS_FINISHED = AT ha finito
|
||||
|
||||
AT_UNKNOWN = AT sconosciuto
|
||||
|
||||
BANNED_FROM_GROUP = divietato dal gruppo
|
||||
|
||||
BAN_EXISTS = il divieto esiste già
|
||||
|
||||
BAN_UNKNOWN = divieto sconosciuto
|
||||
|
||||
BUYER_ALREADY_OWNER = l'acquirente è già proprietario
|
||||
|
||||
CHAT = Le transazioni CHAT non sono mai valide per l'inclusione nei blocchi
|
||||
|
||||
CLOCK_NOT_SYNCED = orologio non sincronizzato
|
||||
|
||||
DUPLICATE_OPTION = opzione duplicata
|
||||
|
||||
GROUP_ALREADY_EXISTS = gruppo già esistente
|
||||
|
||||
GROUP_APPROVAL_DECIDED = approvazione di gruppo già decisa
|
||||
|
||||
GROUP_APPROVAL_NOT_REQUIRED = approvazione di gruppo non richiesto
|
||||
|
||||
GROUP_DOES_NOT_EXIST = gruppo non esiste
|
||||
|
||||
GROUP_ID_MISMATCH = identificazione di gruppo non corrispondente
|
||||
|
||||
GROUP_OWNER_CANNOT_LEAVE = il proprietario del gruppo non può lasciare il gruppo
|
||||
|
||||
HAVE_EQUALS_WANT = la risorsa avere è uguale a la risorsa volere
|
||||
|
||||
INCORRECT_NONCE = PoW nonce sbagliato
|
||||
|
||||
INSUFFICIENT_FEE = tariffa insufficiente
|
||||
|
||||
INVALID_ADDRESS = indirizzo non valido
|
||||
|
||||
INVALID_AMOUNT = importo non valido
|
||||
|
||||
INVALID_ASSET_OWNER = proprietario della risorsa non valido
|
||||
|
||||
INVALID_AT_TRANSACTION = transazione AT non valida
|
||||
|
||||
INVALID_AT_TYPE_LENGTH = lunghezza di "tipo" AT non valida
|
||||
|
||||
INVALID_CREATION_BYTES = byte di creazione non validi
|
||||
|
||||
INVALID_DATA_LENGTH = lunghezza di dati non valida
|
||||
|
||||
INVALID_DESCRIPTION_LENGTH = lunghezza della descrizione non valida
|
||||
|
||||
INVALID_GROUP_APPROVAL_THRESHOLD = soglia di approvazione del gruppo non valida
|
||||
|
||||
INVALID_GROUP_BLOCK_DELAY = ritardo del blocco di approvazione del gruppo non valido
|
||||
|
||||
INVALID_GROUP_ID = identificazione di gruppo non valida
|
||||
|
||||
INVALID_GROUP_OWNER = proprietario di gruppo non valido
|
||||
|
||||
INVALID_LIFETIME = durata della vita non valida
|
||||
|
||||
INVALID_NAME_LENGTH = lunghezza del nome non valida
|
||||
|
||||
INVALID_NAME_OWNER = proprietario del nome non valido
|
||||
|
||||
INVALID_OPTIONS_COUNT = conteggio di opzioni non validi
|
||||
|
||||
INVALID_OPTION_LENGTH = lunghezza di opzioni non valida
|
||||
|
||||
INVALID_ORDER_CREATOR = creatore dell'ordine non valido
|
||||
|
||||
INVALID_PAYMENTS_COUNT = conteggio pagamenti non validi
|
||||
|
||||
INVALID_PUBLIC_KEY = chiave pubblica non valida
|
||||
|
||||
INVALID_QUANTITY = quantità non valida
|
||||
|
||||
INVALID_REFERENCE = riferimento non valido
|
||||
|
||||
INVALID_RETURN = ritorno non valido
|
||||
|
||||
INVALID_REWARD_SHARE_PERCENT = percentuale condivisione di ricompensa non valida
|
||||
|
||||
INVALID_SELLER = venditore non valido
|
||||
|
||||
INVALID_TAGS_LENGTH = lunghezza dei "tag" non valida
|
||||
|
||||
INVALID_TX_GROUP_ID = identificazione di gruppo di transazioni non valida
|
||||
|
||||
INVALID_VALUE_LENGTH = lunghezza "valore" non valida
|
||||
|
||||
INVITE_UNKNOWN = invito di gruppo sconosciuto
|
||||
|
||||
JOIN_REQUEST_EXISTS = la richiesta di iscrizione al gruppo già esiste
|
||||
|
||||
MAXIMUM_REWARD_SHARES = numero massimo di condivisione di ricompensa raggiunto per l'account
|
||||
|
||||
MISSING_CREATOR = creatore mancante
|
||||
|
||||
MULTIPLE_NAMES_FORBIDDEN = è vietata la registrazione di multipli nomi per account
|
||||
|
||||
NAME_ALREADY_FOR_SALE = nome già in vendita
|
||||
|
||||
NAME_ALREADY_REGISTERED = nome già registrato
|
||||
|
||||
NAME_DOES_NOT_EXIST = il nome non esiste
|
||||
|
||||
NAME_NOT_FOR_SALE = il nome non è in vendita
|
||||
|
||||
NAME_NOT_NORMALIZED = il nome non è in forma "normalizzata" Unicode
|
||||
|
||||
NEGATIVE_AMOUNT = importo non valido / negativo
|
||||
|
||||
NEGATIVE_FEE = tariffa non valida / negativa
|
||||
|
||||
NEGATIVE_PRICE = prezzo non valido / negativo
|
||||
|
||||
NOT_GROUP_ADMIN = l'account non è un amministratore di gruppo
|
||||
|
||||
NOT_GROUP_MEMBER = l'account non è un membro del gruppo
|
||||
|
||||
NOT_MINTING_ACCOUNT = l'account non può coniare
|
||||
|
||||
NOT_YET_RELEASED = funzione non ancora rilasciata
|
||||
|
||||
NO_BALANCE = equilibrio insufficiente
|
||||
|
||||
NO_BLOCKCHAIN_LOCK = nodo di blockchain attualmente occupato
|
||||
|
||||
NO_FLAG_PERMISSION = l'account non dispone di questa autorizzazione
|
||||
|
||||
OK = OK
|
||||
|
||||
ORDER_ALREADY_CLOSED = l'ordine di scambio di risorsa è già chiuso
|
||||
|
||||
ORDER_DOES_NOT_EXIST = l'ordine di scambio di risorsa non esiste
|
||||
|
||||
POLL_ALREADY_EXISTS = il sondaggio già esiste
|
||||
|
||||
POLL_DOES_NOT_EXIST = il sondaggio non esiste
|
||||
|
||||
POLL_OPTION_DOES_NOT_EXIST = le opzioni di sondaggio non esistono
|
||||
|
||||
PUBLIC_KEY_UNKNOWN = chiave pubblica sconosciuta
|
||||
|
||||
REWARD_SHARE_UNKNOWN = condivisione di ricompensa sconosciuta
|
||||
|
||||
SELF_SHARE_EXISTS = condivisione di sé (condivisione di ricompensa) già esiste
|
||||
|
||||
TIMESTAMP_TOO_NEW = timestamp troppo nuovo
|
||||
|
||||
TIMESTAMP_TOO_OLD = timestamp troppo vecchio
|
||||
|
||||
TOO_MANY_UNCONFIRMED = l'account ha troppe transazioni non confermate in sospeso
|
||||
|
||||
TRANSACTION_ALREADY_CONFIRMED = la transazione è già confermata
|
||||
|
||||
TRANSACTION_ALREADY_EXISTS = la transazione già esiste
|
||||
|
||||
TRANSACTION_UNKNOWN = transazione sconosciuta
|
||||
|
||||
TX_GROUP_ID_MISMATCH = identificazione di gruppo della transazione non corrisponde
|
@@ -45,7 +45,8 @@
|
||||
"qortalTimestamp": 0,
|
||||
"newAssetPricingTimestamp": 0,
|
||||
"groupApprovalTimestamp": 0,
|
||||
"atFindNextTransactionFix": 0
|
||||
"atFindNextTransactionFix": 0,
|
||||
"newBlockSigHeight": 999999
|
||||
},
|
||||
"genesisInfo": {
|
||||
"version": 4,
|
||||
|
@@ -45,7 +45,8 @@
|
||||
"qortalTimestamp": 0,
|
||||
"newAssetPricingTimestamp": 0,
|
||||
"groupApprovalTimestamp": 0,
|
||||
"atFindNextTransactionFix": 0
|
||||
"atFindNextTransactionFix": 0,
|
||||
"newBlockSigHeight": 999999
|
||||
},
|
||||
"genesisInfo": {
|
||||
"version": 4,
|
||||
|
@@ -45,7 +45,8 @@
|
||||
"qortalTimestamp": 0,
|
||||
"newAssetPricingTimestamp": 0,
|
||||
"groupApprovalTimestamp": 0,
|
||||
"atFindNextTransactionFix": 0
|
||||
"atFindNextTransactionFix": 0,
|
||||
"newBlockSigHeight": 999999
|
||||
},
|
||||
"genesisInfo": {
|
||||
"version": 4,
|
||||
|
@@ -45,7 +45,8 @@
|
||||
"qortalTimestamp": 0,
|
||||
"newAssetPricingTimestamp": 0,
|
||||
"groupApprovalTimestamp": 0,
|
||||
"atFindNextTransactionFix": 0
|
||||
"atFindNextTransactionFix": 0,
|
||||
"newBlockSigHeight": 999999
|
||||
},
|
||||
"genesisInfo": {
|
||||
"version": 4,
|
||||
|
@@ -45,7 +45,8 @@
|
||||
"qortalTimestamp": 0,
|
||||
"newAssetPricingTimestamp": 0,
|
||||
"groupApprovalTimestamp": 0,
|
||||
"atFindNextTransactionFix": 0
|
||||
"atFindNextTransactionFix": 0,
|
||||
"newBlockSigHeight": 999999
|
||||
},
|
||||
"genesisInfo": {
|
||||
"version": 4,
|
||||
|
@@ -45,7 +45,8 @@
|
||||
"qortalTimestamp": 0,
|
||||
"newAssetPricingTimestamp": 0,
|
||||
"groupApprovalTimestamp": 0,
|
||||
"atFindNextTransactionFix": 0
|
||||
"atFindNextTransactionFix": 0,
|
||||
"newBlockSigHeight": 999999
|
||||
},
|
||||
"genesisInfo": {
|
||||
"version": 4,
|
||||
|
@@ -45,7 +45,8 @@
|
||||
"qortalTimestamp": 0,
|
||||
"newAssetPricingTimestamp": 0,
|
||||
"groupApprovalTimestamp": 0,
|
||||
"atFindNextTransactionFix": 0
|
||||
"atFindNextTransactionFix": 0,
|
||||
"newBlockSigHeight": 999999
|
||||
},
|
||||
"genesisInfo": {
|
||||
"version": 4,
|
||||
|
Reference in New Issue
Block a user