Skip to content

Commit

Permalink
Load active peers from previous session saved into file.
Browse files Browse the repository at this point in the history
  • Loading branch information
asoto-iov committed Jan 18, 2024
1 parent 6ba039d commit a1e85d5
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 1 deletion.
7 changes: 7 additions & 0 deletions rskj-core/src/main/java/co/rsk/RskContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -1588,6 +1588,13 @@ protected PeerExplorer getPeerExplorer() {
initialBootNodes.add(address.getHostName() + ":" + address.getPort());
}
}

if (rskSystemProperties.usePeersFromLastSession()) {
List<String> peerLastSession = rskSystemProperties.peerLastSession();
logger.debug("Loading peers from previous session: {}",peerLastSession);
initialBootNodes.addAll(peerLastSession);
}

peerExplorer = new PeerExplorer(
initialBootNodes,
localNode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public class RskSystemProperties extends SystemProperties {
private static final int CHUNK_SIZE = 192;

public static final String PROPERTY_SYNC_TOP_BEST = "sync.topBest";
public static final String USE_PEERS_FROM_LAST_SESSION = "peer.usePeersFromLastSession";

//TODO: REMOVE THIS WHEN THE LocalBLockTests starts working with REMASC
private boolean remascEnabled = true;
Expand Down Expand Up @@ -235,6 +236,10 @@ public boolean skipRemasc() {
return getBoolean("rpc.skipRemasc", false);
}

public boolean usePeersFromLastSession() {
return getBoolean(USE_PEERS_FROM_LAST_SESSION, false);
}

public long peerDiscoveryMessageTimeOut() {
return getLong("peer.discovery.msg.timeout", PD_DEFAULT_TIMEOUT_MESSAGE);
}
Expand Down
20 changes: 20 additions & 0 deletions rskj-core/src/main/java/org/ethereum/config/SystemProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -106,6 +109,7 @@ public abstract class SystemProperties {
public static final String PROPERTY_PERSIST_BLOOMS_CACHE_SNAPSHOT = "cache.blooms.persist-snapshot";

/* Testing */
public static final String LAST_CONNECTED_PEERS_FILE = "lastPeers.txt";
private static final Boolean DEFAULT_VMTEST_LOAD_LOCAL = false;

protected final Config configFromFiles;
Expand Down Expand Up @@ -251,6 +255,18 @@ public List<Node> peerActive() {
return list.stream().map(this::parsePeer).collect(Collectors.toList());
}

public List<String> peerLastSession() {
Path lastConnectedPeersFile = getLastConnectedPeersFilePath();
try {
if (Files.exists(lastConnectedPeersFile)) {
return Files.readAllLines(lastConnectedPeersFile);
}
} catch (IOException e) {
logger.error("Failed to read last connected peers file path {}. Error: {}", lastConnectedPeersFile.toAbsolutePath(), e.getMessage());
}
return Collections.emptyList();
}

private Node parsePeer(ConfigObject configObject) {
if (configObject.get("url") != null) {
String url = configObject.toConfig().getString("url");
Expand Down Expand Up @@ -312,6 +328,10 @@ public String databaseDir() {
return databaseDir == null ? configFromFiles.getString(PROPERTY_BASE_PATH) : databaseDir;
}

public Path getLastConnectedPeersFilePath() {
return Paths.get(databaseDir(), LAST_CONNECTED_PEERS_FILE);
}

public void setDataBaseDir(String dataBaseDir) {
this.databaseDir = dataBaseDir;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
package org.ethereum.net.server;

import co.rsk.config.RskSystemProperties;
import co.rsk.net.Peer;
import co.rsk.net.NodeID;
import co.rsk.net.Peer;
import co.rsk.net.Status;
import co.rsk.net.messages.*;
import co.rsk.scoring.InetAddressUtils;
Expand All @@ -33,11 +33,14 @@
import org.ethereum.core.Transaction;
import org.ethereum.net.message.ReasonCode;
import org.ethereum.sync.SyncPool;
import org.ethereum.util.SimpleFileWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.file.Path;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
Expand Down Expand Up @@ -74,6 +77,8 @@ public class ChannelManagerImpl implements ChannelManager {
private final int maxActivePeers;
private final int maxConnectionsAllowed;
private final int networkCIDR;
private final Path peerListFileDir;
private final SimpleFileWriter fileDataSaver;

private long timeLastLoggedPeers = System.currentTimeMillis();

Expand All @@ -87,6 +92,8 @@ public ChannelManagerImpl(RskSystemProperties config, SyncPool syncPool) {
this.newPeers = new CopyOnWriteArrayList<>();
this.maxConnectionsAllowed = config.maxConnectionsAllowed();
this.networkCIDR = config.networkCIDR();
this.peerListFileDir = config.getLastConnectedPeersFilePath();
fileDataSaver = SimpleFileWriter.getInstance();
}

@Override
Expand All @@ -96,9 +103,28 @@ public void start() {

@Override
public void stop() {
saveActivePeersToFile();
mainWorker.shutdown();
}

private void saveActivePeersToFile() {
if (!activePeers.isEmpty()) {
logger.debug("Shutting down ChannelManagerImpl. Showing list of active peers");

StringBuilder sb = new StringBuilder();
for (Channel peerChannel : activePeers.values()) {
sb.append(peerChannel.getAddress().getCanonicalHostName()).append(":").append(peerChannel.getInetSocketAddress().getPort()).append("\n");
}
logger.debug("Active peer to save: -> {}", sb);

Check failure

Code scanning / CodeQL

Log Injection High

This log entry depends on a
user-provided value
.
try {
fileDataSaver.saveDataIntoFile(sb.toString(), peerListFileDir);
} catch (IOException e) {
logger.error("Error saving active peers to file: {}", e.getMessage());
}
}
}


private void handleNewPeersAndDisconnections() {
this.tryProcessNewPeers();
this.cleanDisconnections();
Expand Down Expand Up @@ -175,6 +201,7 @@ private boolean isRecent(Instant disconnectionTimeout, Instant currentTime) {
}

private void addToActives(Channel peer) {

if (peer.isUsingNewProtocol() || peer.hasEthStatusSucceeded()) {
syncPool.add(peer);
synchronized (activePeersLock) {
Expand Down
52 changes: 52 additions & 0 deletions rskj-core/src/main/java/org/ethereum/util/SimpleFileWriter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* This file is part of RskJ
* Copyright (C) 2023 RSK Labs Ltd.
* (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.ethereum.util;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

public class SimpleFileWriter {
private static final String TMP = ".tmp";
private static SimpleFileWriter instance;

private SimpleFileWriter() {
}

public static SimpleFileWriter getInstance() {
if (instance == null) {
instance = new SimpleFileWriter();
}
return instance;
}

public void saveDataIntoFile(String data, Path filePath) throws IOException {
File tempFile = File.createTempFile(filePath.toString(), TMP);

Check warning

Code scanning / CodeQL

Local information disclosure in a temporary directory Medium

Local information disclosure vulnerability due to use of file readable by other local users.
try (FileWriter writer = new FileWriter(tempFile, false)) {
writer.write(data);
}

Files.move(tempFile.toPath(), filePath, REPLACE_EXISTING);
}
}

3 changes: 3 additions & 0 deletions rskj-core/src/main/resources/expected.conf
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ blockchain = {
}

peer = {

usePeersFromLastSession = <boolean>

active = [
{
url = <url>
Expand Down
3 changes: 3 additions & 0 deletions rskj-core/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ peer {
# Use to connect to specific nodes
active = [ ]

# If true, the node will try to connect to the peers from the last session
usePeersFromLastSession = false

# list of trusted peers the incoming connections is always accepted from. Even if the max amount of connections is reached
# This is used to create a filter of Trusted peers
trusted = [
Expand Down

0 comments on commit a1e85d5

Please sign in to comment.