forked from Qortal/qortal
Fixed warnings, and other improvements.
This commit is contained in:
parent
b571931127
commit
b693a514fd
@ -1173,7 +1173,11 @@ public class ArbitraryResource {
|
||||
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_CRITERIA, error);
|
||||
}
|
||||
|
||||
final Long minLatestBlockTimestamp = NTP.getTime() - (60 * 60 * 1000L);
|
||||
final Long now = NTP.getTime();
|
||||
if (now == null) {
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.NO_TIME_SYNC);
|
||||
}
|
||||
final Long minLatestBlockTimestamp = now - (60 * 60 * 1000L);
|
||||
if (!Controller.getInstance().isUpToDate(minLatestBlockTimestamp)) {
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.BLOCKCHAIN_NEEDS_SYNC);
|
||||
}
|
||||
@ -1231,7 +1235,7 @@ public class ArbitraryResource {
|
||||
// The actual data will be in a randomly-named subfolder of tempDirectory
|
||||
// Remove hidden folders, i.e. starting with "_", as some systems can add them, e.g. "__MACOSX"
|
||||
String[] files = tempDirectory.toFile().list((parent, child) -> !child.startsWith("_"));
|
||||
if (files.length == 1) { // Single directory or file only
|
||||
if (files != null && files.length == 1) { // Single directory or file only
|
||||
path = Paths.get(tempDirectory.toString(), files[0]).toString();
|
||||
}
|
||||
}
|
||||
|
@ -54,10 +54,6 @@ public class ArbitraryDataBuilder {
|
||||
/**
|
||||
* Process transactions, but do not build anything
|
||||
* This is useful for checking the status of a given resource
|
||||
*
|
||||
* @throws DataException
|
||||
* @throws IOException
|
||||
* @throws MissingDataException
|
||||
*/
|
||||
public void process() throws DataException, IOException, MissingDataException {
|
||||
this.fetchTransactions();
|
||||
@ -69,10 +65,6 @@ public class ArbitraryDataBuilder {
|
||||
|
||||
/**
|
||||
* Build the latest state of a given resource
|
||||
*
|
||||
* @throws DataException
|
||||
* @throws IOException
|
||||
* @throws MissingDataException
|
||||
*/
|
||||
public void build() throws DataException, IOException, MissingDataException {
|
||||
this.process();
|
||||
|
@ -9,7 +9,6 @@ import org.qortal.arbitrary.exception.MissingDataException;
|
||||
import org.qortal.arbitrary.misc.Service;
|
||||
import org.qortal.controller.arbitrary.ArbitraryDataBuildManager;
|
||||
import org.qortal.controller.arbitrary.ArbitraryDataManager;
|
||||
import org.qortal.controller.arbitrary.ArbitraryDataStorageManager;
|
||||
import org.qortal.crypto.AES;
|
||||
import org.qortal.data.transaction.ArbitraryTransactionData;
|
||||
import org.qortal.data.transaction.ArbitraryTransactionData.*;
|
||||
@ -154,9 +153,6 @@ public class ArbitraryDataReader {
|
||||
* If no exception is thrown, you can then use getFilePath() to access the data immediately after returning
|
||||
*
|
||||
* @param overwrite - set to true to force rebuild an existing cache
|
||||
* @throws IOException
|
||||
* @throws DataException
|
||||
* @throws MissingDataException
|
||||
*/
|
||||
public void loadSynchronously(boolean overwrite) throws DataException, IOException, MissingDataException {
|
||||
try {
|
||||
@ -223,7 +219,6 @@ public class ArbitraryDataReader {
|
||||
/**
|
||||
* Working directory should only be deleted on failure, since it is currently used to
|
||||
* serve a cached version of the resource for subsequent requests.
|
||||
* @throws IOException
|
||||
*/
|
||||
private void deleteWorkingDirectory() {
|
||||
try {
|
||||
@ -303,7 +298,7 @@ public class ArbitraryDataReader {
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new DataException(String.format("Unknown resource ID type specified: %s", resourceIdType.toString()));
|
||||
throw new DataException(String.format("Unknown resource ID type specified: %s", resourceIdType));
|
||||
}
|
||||
}
|
||||
|
||||
@ -368,6 +363,9 @@ public class ArbitraryDataReader {
|
||||
// Load data file(s)
|
||||
ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromTransactionData(transactionData);
|
||||
ArbitraryTransactionUtils.checkAndRelocateMiscFiles(transactionData);
|
||||
if (arbitraryDataFile == null) {
|
||||
throw new DataException(String.format("arbitraryDataFile is null"));
|
||||
}
|
||||
|
||||
if (!arbitraryDataFile.allFilesExist()) {
|
||||
if (ListUtils.isNameBlocked(transactionData.getName())) {
|
||||
|
@ -150,6 +150,9 @@ public class ArbitraryDataResource {
|
||||
|
||||
for (ArbitraryTransactionData transactionData : transactionDataList) {
|
||||
ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromTransactionData(transactionData);
|
||||
if (arbitraryDataFile == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Delete any chunks or complete files from each transaction
|
||||
arbitraryDataFile.deleteAll(deleteMetadata);
|
||||
|
@ -504,110 +504,118 @@ public class OnlineAccountsManager {
|
||||
computeOurAccountsForTimestamp(onlineAccountsTimestamp);
|
||||
}
|
||||
|
||||
private boolean computeOurAccountsForTimestamp(long onlineAccountsTimestamp) {
|
||||
List<MintingAccountData> mintingAccounts;
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
mintingAccounts = repository.getAccountRepository().getMintingAccounts();
|
||||
private boolean computeOurAccountsForTimestamp(Long onlineAccountsTimestamp) {
|
||||
if (onlineAccountsTimestamp != null) {
|
||||
List<MintingAccountData> mintingAccounts;
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
mintingAccounts = repository.getAccountRepository().getMintingAccounts();
|
||||
|
||||
// We have no accounts to send
|
||||
if (mintingAccounts.isEmpty())
|
||||
// We have no accounts to send
|
||||
if (mintingAccounts.isEmpty())
|
||||
return false;
|
||||
|
||||
// Only active reward-shares allowed
|
||||
Iterator<MintingAccountData> iterator = mintingAccounts.iterator();
|
||||
int i = 0;
|
||||
while (iterator.hasNext()) {
|
||||
MintingAccountData mintingAccountData = iterator.next();
|
||||
|
||||
RewardShareData rewardShareData = repository.getAccountRepository().getRewardShare(mintingAccountData.getPublicKey());
|
||||
if (rewardShareData == null) {
|
||||
// Reward-share doesn't even exist - probably not a good sign
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
Account mintingAccount = new Account(repository, rewardShareData.getMinter());
|
||||
if (!mintingAccount.canMint()) {
|
||||
// Minting-account component of reward-share can no longer mint - disregard
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (++i > 1 + 1) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} catch (DataException e) {
|
||||
LOGGER.warn(String.format("Repository issue trying to fetch minting accounts: %s", e.getMessage()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only active reward-shares allowed
|
||||
Iterator<MintingAccountData> iterator = mintingAccounts.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
MintingAccountData mintingAccountData = iterator.next();
|
||||
byte[] timestampBytes = Longs.toByteArray(onlineAccountsTimestamp);
|
||||
List<OnlineAccountData> ourOnlineAccounts = new ArrayList<>();
|
||||
|
||||
RewardShareData rewardShareData = repository.getAccountRepository().getRewardShare(mintingAccountData.getPublicKey());
|
||||
if (rewardShareData == null) {
|
||||
// Reward-share doesn't even exist - probably not a good sign
|
||||
iterator.remove();
|
||||
int remaining = mintingAccounts.size();
|
||||
for (MintingAccountData mintingAccountData : mintingAccounts) {
|
||||
remaining--;
|
||||
byte[] privateKey = mintingAccountData.getPrivateKey();
|
||||
byte[] publicKey = Crypto.toPublicKey(privateKey);
|
||||
|
||||
// We don't want to compute the online account nonce and signature again if it already exists
|
||||
Set<OnlineAccountData> onlineAccounts = this.currentOnlineAccounts.computeIfAbsent(onlineAccountsTimestamp, k -> ConcurrentHashMap.newKeySet());
|
||||
boolean alreadyExists = onlineAccounts.stream().anyMatch(a -> Arrays.equals(a.getPublicKey(), publicKey));
|
||||
if (alreadyExists) {
|
||||
this.hasOurOnlineAccounts = true;
|
||||
|
||||
if (remaining > 0) {
|
||||
// Move on to next account
|
||||
continue;
|
||||
} else {
|
||||
// Everything exists, so return true
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate bytes for mempow
|
||||
byte[] mempowBytes;
|
||||
try {
|
||||
mempowBytes = this.getMemoryPoWBytes(publicKey, onlineAccountsTimestamp);
|
||||
} catch (IOException e) {
|
||||
LOGGER.info("Unable to create bytes for MemoryPoW. Moving on to next account...");
|
||||
continue;
|
||||
}
|
||||
|
||||
Account mintingAccount = new Account(repository, rewardShareData.getMinter());
|
||||
if (!mintingAccount.canMint()) {
|
||||
// Minting-account component of reward-share can no longer mint - disregard
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} catch (DataException e) {
|
||||
LOGGER.warn(String.format("Repository issue trying to fetch minting accounts: %s", e.getMessage()));
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] timestampBytes = Longs.toByteArray(onlineAccountsTimestamp);
|
||||
List<OnlineAccountData> ourOnlineAccounts = new ArrayList<>();
|
||||
|
||||
int remaining = mintingAccounts.size();
|
||||
for (MintingAccountData mintingAccountData : mintingAccounts) {
|
||||
remaining--;
|
||||
byte[] privateKey = mintingAccountData.getPrivateKey();
|
||||
byte[] publicKey = Crypto.toPublicKey(privateKey);
|
||||
|
||||
// We don't want to compute the online account nonce and signature again if it already exists
|
||||
Set<OnlineAccountData> onlineAccounts = this.currentOnlineAccounts.computeIfAbsent(onlineAccountsTimestamp, k -> ConcurrentHashMap.newKeySet());
|
||||
boolean alreadyExists = onlineAccounts.stream().anyMatch(a -> Arrays.equals(a.getPublicKey(), publicKey));
|
||||
if (alreadyExists) {
|
||||
this.hasOurOnlineAccounts = true;
|
||||
|
||||
if (remaining > 0) {
|
||||
// Move on to next account
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// Everything exists, so return true
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate bytes for mempow
|
||||
byte[] mempowBytes;
|
||||
try {
|
||||
mempowBytes = this.getMemoryPoWBytes(publicKey, onlineAccountsTimestamp);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOGGER.info("Unable to create bytes for MemoryPoW. Moving on to next account...");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compute nonce
|
||||
Integer nonce;
|
||||
try {
|
||||
nonce = this.computeMemoryPoW(mempowBytes, publicKey, onlineAccountsTimestamp);
|
||||
if (nonce == null) {
|
||||
// A nonce is required
|
||||
// Compute nonce
|
||||
Integer nonce;
|
||||
try {
|
||||
nonce = this.computeMemoryPoW(mempowBytes, publicKey, onlineAccountsTimestamp);
|
||||
if (nonce == null) {
|
||||
// A nonce is required
|
||||
return false;
|
||||
}
|
||||
} catch (TimeoutException e) {
|
||||
LOGGER.info(String.format("Timed out computing nonce for account %.8s", Base58.encode(publicKey)));
|
||||
return false;
|
||||
}
|
||||
} catch (TimeoutException e) {
|
||||
LOGGER.info(String.format("Timed out computing nonce for account %.8s", Base58.encode(publicKey)));
|
||||
|
||||
byte[] signature = Qortal25519Extras.signForAggregation(privateKey, timestampBytes);
|
||||
|
||||
// Our account is online
|
||||
OnlineAccountData ourOnlineAccountData = new OnlineAccountData(onlineAccountsTimestamp, signature, publicKey, nonce);
|
||||
|
||||
// Make sure to verify before adding
|
||||
if (verifyMemoryPoW(ourOnlineAccountData, null)) {
|
||||
ourOnlineAccounts.add(ourOnlineAccountData);
|
||||
}
|
||||
}
|
||||
|
||||
this.hasOurOnlineAccounts = !ourOnlineAccounts.isEmpty();
|
||||
|
||||
boolean hasInfoChanged = addAccounts(ourOnlineAccounts);
|
||||
|
||||
if (!hasInfoChanged)
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] signature = Qortal25519Extras.signForAggregation(privateKey, timestampBytes);
|
||||
Network.getInstance().broadcast(peer -> new OnlineAccountsV3Message(ourOnlineAccounts));
|
||||
|
||||
// Our account is online
|
||||
OnlineAccountData ourOnlineAccountData = new OnlineAccountData(onlineAccountsTimestamp, signature, publicKey, nonce);
|
||||
LOGGER.debug("Broadcasted {} online account{} with timestamp {}", ourOnlineAccounts.size(), (ourOnlineAccounts.size() != 1 ? "s" : ""), onlineAccountsTimestamp);
|
||||
|
||||
// Make sure to verify before adding
|
||||
if (verifyMemoryPoW(ourOnlineAccountData, null)) {
|
||||
ourOnlineAccounts.add(ourOnlineAccountData);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
this.hasOurOnlineAccounts = !ourOnlineAccounts.isEmpty();
|
||||
|
||||
boolean hasInfoChanged = addAccounts(ourOnlineAccounts);
|
||||
|
||||
if (!hasInfoChanged)
|
||||
return false;
|
||||
|
||||
Network.getInstance().broadcast(peer -> new OnlineAccountsV3Message(ourOnlineAccounts));
|
||||
|
||||
LOGGER.debug("Broadcasted {} online account{} with timestamp {}", ourOnlineAccounts.size(), (ourOnlineAccounts.size() != 1 ? "s" : ""), onlineAccountsTimestamp);
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user