mirror of
https://github.com/Qortal/qortal.git
synced 2025-07-23 04:36:50 +00:00
Don't allow a row to be added to ArbitraryPeers (or the message to be rebroadcast) if an entry already exists with the same hash and host/ip.
This avoids duplicate entries from the same host/ip with differing ports. This can occur due to some requests using ephemeral port numbers. Ideally we would filter these out altogether, but this at least acts as a safety net to prevent a very cluttered db and associated "broadcast storm". The main tradeoff here is that multiple nodes on the same IP address will be recorded as a single entry. This doesn't seem like it will be a major limitation, because one of them will remain available.
This commit is contained in:
@@ -386,9 +386,11 @@ public class ArbitraryDataManager extends Thread {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
for (byte[] signature : signatures) {
|
||||
|
||||
// Check if a record already exists for this hash/peer combination
|
||||
// Check if a record already exists for this hash/host combination
|
||||
// The port is not checked here - only the host/ip - in order to avoid duplicates
|
||||
// from filling up the db due to dynamic/ephemeral ports
|
||||
ArbitraryPeerData existingEntry = repository.getArbitraryRepository()
|
||||
.getArbitraryPeerDataForSignatureAndPeer(signature, peer.getPeerData().getAddress().toString());
|
||||
.getArbitraryPeerDataForSignatureAndHost(signature, peer.getPeerData().getAddress().getHost());
|
||||
|
||||
if (existingEntry == null) {
|
||||
// We haven't got a record of this mapping yet, so add it
|
||||
|
@@ -33,6 +33,8 @@ public interface ArbitraryRepository {
|
||||
|
||||
public ArbitraryPeerData getArbitraryPeerDataForSignatureAndPeer(byte[] signature, String peerAddress) throws DataException;
|
||||
|
||||
public ArbitraryPeerData getArbitraryPeerDataForSignatureAndHost(byte[] signature, String host) throws DataException;
|
||||
|
||||
public void save(ArbitraryPeerData arbitraryPeerData) throws DataException;
|
||||
|
||||
public void delete(ArbitraryPeerData arbitraryPeerData) throws DataException;
|
||||
|
@@ -498,6 +498,37 @@ public class HSQLDBArbitraryRepository implements ArbitraryRepository {
|
||||
}
|
||||
}
|
||||
|
||||
public ArbitraryPeerData getArbitraryPeerDataForSignatureAndHost(byte[] signature, String host) throws DataException {
|
||||
// Hash the signature so it fits within 32 bytes
|
||||
byte[] hashedSignature = Crypto.digest(signature);
|
||||
|
||||
// Create a host wildcard string which allows any port
|
||||
String hostWildcard = String.format("%s:%%", host);
|
||||
|
||||
String sql = "SELECT hash, peer_address, successes, failures, last_attempted, last_retrieved " +
|
||||
"FROM ArbitraryPeers " +
|
||||
"WHERE hash = ? AND peer_address LIKE ?";
|
||||
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, hashedSignature, hostWildcard)) {
|
||||
if (resultSet == null)
|
||||
return null;
|
||||
|
||||
byte[] hash = resultSet.getBytes(1);
|
||||
String peerAddr = resultSet.getString(2);
|
||||
Integer successes = resultSet.getInt(3);
|
||||
Integer failures = resultSet.getInt(4);
|
||||
Long lastAttempted = resultSet.getLong(5);
|
||||
Long lastRetrieved = resultSet.getLong(6);
|
||||
|
||||
ArbitraryPeerData arbitraryPeerData = new ArbitraryPeerData(hash, peerAddr, successes, failures,
|
||||
lastAttempted, lastRetrieved);
|
||||
|
||||
return arbitraryPeerData;
|
||||
} catch (SQLException e) {
|
||||
throw new DataException("Unable to fetch arbitrary peer data from repository", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(ArbitraryPeerData arbitraryPeerData) throws DataException {
|
||||
HSQLDBSaver saveHelper = new HSQLDBSaver("ArbitraryPeers");
|
||||
|
Reference in New Issue
Block a user