forked from Qortal/qortal
Merge pull request #238 from AlphaX-Qortal/master
Added real address to API results - Currently the address shown in the API results when querying blocks, shows an address formed by the 'reward share public key', this address is not useful for viewing, as it is not the address utilized for QORT. This change makes it so the 'real' Qortal address is displayed instead of this useless address. Thanks @AlphaX-Qortal Added group member check to validations - validation fixes. Network changes - Moved unnecessary 'we already have connection' messages from info logging to debug. Updated minPeerVersion default to current release version. (4.6.5). Updated default peer list. Updated syntax. Updated formatting. Updated dependencies Thanks @AlphaX-Qortal
This commit is contained in:
commit
a8d73926b3
4
pom.xml
4
pom.xml
@ -22,7 +22,7 @@
|
||||
<dagger.version>1.2.2</dagger.version>
|
||||
<extendedset.version>0.12.3</extendedset.version>
|
||||
<git-commit-id-plugin.version>4.9.10</git-commit-id-plugin.version>
|
||||
<grpc.version>1.68.1</grpc.version>
|
||||
<grpc.version>1.68.2</grpc.version>
|
||||
<guava.version>33.3.1-jre</guava.version>
|
||||
<hamcrest-library.version>2.2</hamcrest-library.version>
|
||||
<homoglyph.version>1.2.1</homoglyph.version>
|
||||
@ -35,7 +35,7 @@
|
||||
<jetty.version>9.4.56.v20240826</jetty.version>
|
||||
<json-simple.version>1.1.1</json-simple.version>
|
||||
<json.version>20240303</json.version>
|
||||
<jsoup.version>1.18.1</jsoup.version>
|
||||
<jsoup.version>1.18.3</jsoup.version>
|
||||
<junit-jupiter-engine.version>5.11.0-M2</junit-jupiter-engine.version>
|
||||
<lifecycle-mapping.version>1.0.0</lifecycle-mapping.version>
|
||||
<log4j.version>2.23.1</log4j.version>
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public enum Handshake {
|
||||
|
||||
String versionString = helloMessage.getVersionString();
|
||||
|
||||
Matcher matcher = peer.VERSION_PATTERN.matcher(versionString);
|
||||
Matcher matcher = Peer.VERSION_PATTERN.matcher(versionString);
|
||||
if (!matcher.lookingAt()) {
|
||||
LOGGER.debug(() -> String.format("Peer %s sent invalid HELLO version string '%s'", peer, versionString));
|
||||
return null;
|
||||
@ -71,7 +71,7 @@ public enum Handshake {
|
||||
|
||||
// Ensure the peer is running at least the version specified in MIN_PEER_VERSION
|
||||
if (!peer.isAtLeastVersion(MIN_PEER_VERSION)) {
|
||||
LOGGER.debug(String.format("Ignoring peer %s because it is on an old version (%s)", peer, versionString));
|
||||
LOGGER.debug("Ignoring peer {} because it is on an old version ({})", peer, versionString);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ public enum Handshake {
|
||||
// Ensure the peer is running at least the minimum version allowed for connections
|
||||
final String minPeerVersion = Settings.getInstance().getMinPeerVersion();
|
||||
if (!peer.isAtLeastVersion(minPeerVersion)) {
|
||||
LOGGER.debug(String.format("Ignoring peer %s because it is on an old version (%s)", peer, versionString));
|
||||
LOGGER.debug("Ignoring peer {} because it is on an old version ({})", peer, versionString);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -106,7 +106,7 @@ public enum Handshake {
|
||||
byte[] peersPublicKey = challengeMessage.getPublicKey();
|
||||
byte[] peersChallenge = challengeMessage.getChallenge();
|
||||
|
||||
// If public key matches our public key then we've connected to self
|
||||
// If public key matches our public key, then we've connected to self
|
||||
byte[] ourPublicKey = Network.getInstance().getOurPublicKey();
|
||||
if (Arrays.equals(ourPublicKey, peersPublicKey)) {
|
||||
// If outgoing connection then record destination as self so we don't try again
|
||||
@ -121,11 +121,11 @@ public enum Handshake {
|
||||
peer.disconnect("failed to send CHALLENGE to self");
|
||||
|
||||
/*
|
||||
* We return CHALLENGE here to prevent us from closing connection. Closing
|
||||
* connection currently preempts remote end from reading any pending messages,
|
||||
* We return the CHALLENGE here to prevent us from closing the connection.
|
||||
* Closing the connection currently preempts the remote end from reading any pending messages,
|
||||
* specifically the CHALLENGE message we just sent above. When our 'remote'
|
||||
* outbound counterpart reads our message, they will close both connections.
|
||||
* Failing that, our connection will timeout or a future handshake error will
|
||||
* Failing that, our connection will time out or a future handshake error will
|
||||
* occur.
|
||||
*/
|
||||
return CHALLENGE;
|
||||
@ -135,7 +135,7 @@ public enum Handshake {
|
||||
// Are we already connected to this peer?
|
||||
Peer existingPeer = Network.getInstance().getHandshakedPeerWithPublicKey(peersPublicKey);
|
||||
if (existingPeer != null) {
|
||||
LOGGER.info(() -> String.format("We already have a connection with peer %s - discarding", peer));
|
||||
LOGGER.debug(() -> String.format("We already have a connection with peer %s - discarding", peer));
|
||||
// Handshake failure - caller will deal with disconnect
|
||||
return null;
|
||||
}
|
||||
@ -148,7 +148,7 @@ public enum Handshake {
|
||||
|
||||
@Override
|
||||
public void action(Peer peer) {
|
||||
// Send challenge
|
||||
// Send a challenge
|
||||
byte[] publicKey = Network.getInstance().getOurPublicKey();
|
||||
byte[] challenge = peer.getOurChallenge();
|
||||
|
||||
@ -254,16 +254,17 @@ public enum Handshake {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(Handshake.class);
|
||||
|
||||
/** Maximum allowed difference between peer's reported timestamp and when they connected, in milliseconds. */
|
||||
/** The Maximum allowed difference between peer's reported timestamp and when they connected, in milliseconds. */
|
||||
private static final long MAX_TIMESTAMP_DELTA = 30 * 1000L; // ms
|
||||
|
||||
private static final long PEER_VERSION_131 = 0x0100030001L;
|
||||
|
||||
/** Minimum peer version that we are allowed to communicate with */
|
||||
private static final String MIN_PEER_VERSION = "4.1.1";
|
||||
private static final String MIN_PEER_VERSION = "4.6.5";
|
||||
|
||||
private static final int POW_BUFFER_SIZE_PRE_131 = 8 * 1024 * 1024; // bytes
|
||||
private static final int POW_DIFFICULTY_PRE_131 = 8; // leading zero bits
|
||||
|
||||
// Can always be made harder in the future...
|
||||
private static final int POW_BUFFER_SIZE_POST_131 = 2 * 1024 * 1024; // bytes
|
||||
private static final int POW_DIFFICULTY_POST_131 = 2; // leading zero bits
|
||||
@ -275,12 +276,11 @@ public enum Handshake {
|
||||
|
||||
public final MessageType expectedMessageType;
|
||||
|
||||
private Handshake(MessageType expectedMessageType) {
|
||||
Handshake(MessageType expectedMessageType) {
|
||||
this.expectedMessageType = expectedMessageType;
|
||||
}
|
||||
|
||||
public abstract Handshake onMessage(Peer peer, Message message);
|
||||
|
||||
public abstract void action(Peer peer);
|
||||
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ public class Network {
|
||||
"node.qortal.ru", "node2.qortal.ru", "node3.qortal.ru", "node.qortal.uk", "node22.qortal.org",
|
||||
"cinfu1.crowetic.com", "node.cwd.systems", "bootstrap.cwd.systems", "node1.qortalnodes.live",
|
||||
"node2.qortalnodes.live", "node3.qortalnodes.live", "node4.qortalnodes.live", "node5.qortalnodes.live",
|
||||
"node6.qortalnodes.live", "node7.qortalnodes.live", "node8.qortalnodes.live"
|
||||
"node.qortalnodes.live", "qortex.live",
|
||||
};
|
||||
|
||||
private static final long NETWORK_EPC_KEEPALIVE = 5L; // seconds
|
||||
@ -149,7 +149,7 @@ public class Network {
|
||||
|
||||
private final Lock mergePeersLock = new ReentrantLock();
|
||||
|
||||
private List<String> ourExternalIpAddressHistory = new ArrayList<>();
|
||||
private final List<String> ourExternalIpAddressHistory = new ArrayList<>();
|
||||
private String ourExternalIpAddress = null;
|
||||
private int ourExternalPort = Settings.getInstance().getListenPort();
|
||||
|
||||
@ -167,7 +167,7 @@ public class Network {
|
||||
ExecutorService networkExecutor = new ThreadPoolExecutor(2,
|
||||
Settings.getInstance().getMaxNetworkThreadPoolSize(),
|
||||
NETWORK_EPC_KEEPALIVE, TimeUnit.SECONDS,
|
||||
new SynchronousQueue<Runnable>(),
|
||||
new SynchronousQueue<>(),
|
||||
new NamedThreadFactory("Network-EPC", Settings.getInstance().getNetworkThreadPriority()));
|
||||
networkEPC = new NetworkProcessor(networkExecutor);
|
||||
}
|
||||
@ -314,7 +314,7 @@ public class Network {
|
||||
|
||||
public List<Peer> getImmutableConnectedDataPeers() {
|
||||
return this.getImmutableConnectedPeers().stream()
|
||||
.filter(p -> p.isDataPeer())
|
||||
.filter(Peer::isDataPeer)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@ -346,7 +346,7 @@ public class Network {
|
||||
public boolean requestDataFromPeer(String peerAddressString, byte[] signature) {
|
||||
if (peerAddressString != null) {
|
||||
PeerAddress peerAddress = PeerAddress.fromString(peerAddressString);
|
||||
PeerData peerData = null;
|
||||
PeerData peerData;
|
||||
|
||||
// Reuse an existing PeerData instance if it's already in the known peers list
|
||||
synchronized (this.allKnownPeers) {
|
||||
@ -370,9 +370,9 @@ public class Network {
|
||||
|
||||
// Check if we're already connected to and handshaked with this peer
|
||||
Peer connectedPeer = this.getImmutableConnectedPeers().stream()
|
||||
.filter(p -> p.getPeerData().getAddress().equals(peerAddress))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
.filter(p -> p.getPeerData().getAddress().equals(peerAddress))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
boolean isConnected = (connectedPeer != null);
|
||||
|
||||
@ -710,7 +710,7 @@ public class Network {
|
||||
return true;
|
||||
}
|
||||
|
||||
private Peer getConnectablePeer(final Long now) throws InterruptedException {
|
||||
private Peer getConnectablePeer(final Long now) {
|
||||
// We can't block here so use tryRepository(). We don't NEED to connect a new peer.
|
||||
try (Repository repository = RepositoryManager.tryRepository()) {
|
||||
if (repository == null) {
|
||||
@ -807,7 +807,7 @@ public class Network {
|
||||
// Find peers that have reached their maximum connection age, and disconnect them
|
||||
List<Peer> peersToDisconnect = this.getImmutableConnectedPeers().stream()
|
||||
.filter(peer -> !peer.isSyncInProgress())
|
||||
.filter(peer -> peer.hasReachedMaxConnectionAge())
|
||||
.filter(Peer::hasReachedMaxConnectionAge)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (peersToDisconnect != null && !peersToDisconnect.isEmpty()) {
|
||||
@ -996,9 +996,9 @@ public class Network {
|
||||
}
|
||||
|
||||
// Add to per-message thread count (first initializing to 0 if not already present)
|
||||
threadsPerMessageType.computeIfAbsent(message.getType(), key -> 0);
|
||||
threadsPerMessageType.putIfAbsent(message.getType(), 0);
|
||||
threadsPerMessageType.computeIfPresent(message.getType(), (key, value) -> value + 1);
|
||||
|
||||
|
||||
// Add to total thread count
|
||||
synchronized (this) {
|
||||
totalThreadCount++;
|
||||
@ -1037,7 +1037,7 @@ public class Network {
|
||||
}
|
||||
|
||||
// Remove from per-message thread count (first initializing to 0 if not already present)
|
||||
threadsPerMessageType.computeIfAbsent(message.getType(), key -> 0);
|
||||
threadsPerMessageType.putIfAbsent(message.getType(), 0);
|
||||
threadsPerMessageType.computeIfPresent(message.getType(), (key, value) -> value - 1);
|
||||
|
||||
// Remove from total thread count
|
||||
@ -1135,7 +1135,7 @@ public class Network {
|
||||
Peer existingPeer = getHandshakedPeerWithPublicKey(peer.getPeersPublicKey());
|
||||
// NOTE: actual object reference compare, not Peer.equals()
|
||||
if (existingPeer != peer) {
|
||||
LOGGER.info("[{}] We already have a connection with peer {} - discarding",
|
||||
LOGGER.debug("[{}] We already have a connection with peer {} - discarding",
|
||||
peer.getPeerConnectionId(), peer);
|
||||
peer.disconnect("existing connection");
|
||||
return;
|
||||
@ -1216,29 +1216,7 @@ public class Network {
|
||||
* Returns PEERS message made from peers we've connected to recently, and this node's details
|
||||
*/
|
||||
public Message buildPeersMessage(Peer peer) {
|
||||
List<PeerData> knownPeers = this.getAllKnownPeers();
|
||||
|
||||
// Filter out peers that we've not connected to ever or within X milliseconds
|
||||
final long connectionThreshold = NTP.getTime() - RECENT_CONNECTION_THRESHOLD;
|
||||
Predicate<PeerData> notRecentlyConnected = peerData -> {
|
||||
final Long lastAttempted = peerData.getLastAttempted();
|
||||
final Long lastConnected = peerData.getLastConnected();
|
||||
|
||||
if (lastAttempted == null || lastConnected == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lastConnected < lastAttempted) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lastConnected < connectionThreshold) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
knownPeers.removeIf(notRecentlyConnected);
|
||||
final var knownPeers = getPeerData();
|
||||
|
||||
List<PeerAddress> peerAddresses = new ArrayList<>();
|
||||
|
||||
@ -1262,6 +1240,29 @@ public class Network {
|
||||
return new PeersV2Message(peerAddresses);
|
||||
}
|
||||
|
||||
private List<PeerData> getPeerData() {
|
||||
List<PeerData> knownPeers = this.getAllKnownPeers();
|
||||
|
||||
// Filter out peers that we've not connected to ever or within X milliseconds
|
||||
final long connectionThreshold = NTP.getTime() - RECENT_CONNECTION_THRESHOLD;
|
||||
Predicate<PeerData> notRecentlyConnected = peerData -> {
|
||||
final Long lastAttempted = peerData.getLastAttempted();
|
||||
final Long lastConnected = peerData.getLastConnected();
|
||||
|
||||
if (lastAttempted == null || lastConnected == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lastConnected < lastAttempted) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return lastConnected < connectionThreshold;
|
||||
};
|
||||
knownPeers.removeIf(notRecentlyConnected);
|
||||
return knownPeers;
|
||||
}
|
||||
|
||||
/** Builds either (legacy) HeightV2Message or (newer) BlockSummariesV2Message, depending on peer version.
|
||||
*
|
||||
* @return Message, or null if DataException was thrown.
|
||||
@ -1328,7 +1329,7 @@ public class Network {
|
||||
return;
|
||||
}
|
||||
String host = parts[0];
|
||||
|
||||
|
||||
try {
|
||||
InetAddress addr = InetAddress.getByName(host);
|
||||
if (addr.isAnyLocalAddress() || addr.isSiteLocalAddress()) {
|
||||
@ -1369,12 +1370,12 @@ public class Network {
|
||||
for (int i = size-1; i >= 0; i--) {
|
||||
String reading = ipAddressHistory.get(i);
|
||||
if (lastReading != null) {
|
||||
if (Objects.equals(reading, lastReading)) {
|
||||
if (Objects.equals(reading, lastReading)) {
|
||||
consecutiveReadings++;
|
||||
}
|
||||
else {
|
||||
consecutiveReadings = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
consecutiveReadings = 0;
|
||||
}
|
||||
}
|
||||
lastReading = reading;
|
||||
}
|
||||
@ -1515,12 +1516,8 @@ public class Network {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (peerData.getLastConnected() == null
|
||||
|| peerData.getLastConnected() > now - OLD_PEER_CONNECTION_PERIOD) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return peerData.getLastConnected() == null
|
||||
|| peerData.getLastConnected() > now - OLD_PEER_CONNECTION_PERIOD;
|
||||
};
|
||||
|
||||
// Disregard peers that are NOT 'old'
|
||||
@ -1655,7 +1652,7 @@ public class Network {
|
||||
|
||||
// Stop processing threads
|
||||
try {
|
||||
if (!this.networkEPC.shutdown(5000)) {
|
||||
if (!this.networkEPC.shutdown(10000)) {
|
||||
LOGGER.warn("Network threads failed to terminate");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
@ -1667,5 +1664,4 @@ public class Network {
|
||||
peer.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user