Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,37 @@ public class CommonParameter {
@Getter
@Setter
public int minParticipationRate;
// -- Tor anonymous transaction broadcast --
// When enabled, locally-originated transactions are sent through the Tor SOCKS5 proxy
// to the HTTP broadcast API of standard (unmodified) TRON nodes instead of being advertised
// to P2P peers, hiding the originating node's IP.
@Getter
@Setter
public boolean torBroadcastEnable = false;
@Getter
@Setter
public String torSocksHost = "127.0.0.1";
@Getter
@Setter
public int torSocksPort = 9050;
@Getter
@Setter
public int torConnectTimeout = 30000;
@Getter
@Setter
public int torReadTimeout = 30000;
@Getter
@Setter
public int torBroadcastCount = 2;
@Getter
@Setter
public boolean torCircuitIsolation = true;
@Getter
@Setter
public int torControlPort = 0;
@Getter
@Setter
public String torControlPassword = "";
@Getter
public P2pConfig p2pConfig;
@Getter
Expand Down Expand Up @@ -426,7 +457,9 @@ public class CommonParameter {
// from clearParam(), consistent with mainnet.conf
public List<InetAddress> passiveNodes = new ArrayList<>();
@Getter
public List<InetSocketAddress> fastForwardNodes; // clearParam: new ArrayList<>()
// Default to an empty list (never null) so consumers that capture it at class-load time
// (e.g. PeerConnection's static relayNodes) can't capture a null before Args is initialised.
public List<InetSocketAddress> fastForwardNodes = new ArrayList<>();
@Getter
public int maxFastForwardNum; // clearParam: 4
@Getter
Expand Down
78 changes: 78 additions & 0 deletions common/src/main/java/org/tron/core/config/args/NodeConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,73 @@ public class NodeConfig {
private List<String> fastForward = new ArrayList<>();
private List<String> disabledApi = new ArrayList<>();

// node.tor.* — anonymous outbound transaction broadcast over the Tor SOCKS5 proxy.
// Read manually in fromConfig() so an absent [node.tor] block keeps prior behaviour
// and no reference.conf defaults are required.
@Getter(lombok.AccessLevel.NONE)
@Setter(lombok.AccessLevel.NONE)
private boolean torBroadcastEnable = false;
@Getter(lombok.AccessLevel.NONE)
@Setter(lombok.AccessLevel.NONE)
private String torSocksHost = "127.0.0.1";
@Getter(lombok.AccessLevel.NONE)
@Setter(lombok.AccessLevel.NONE)
private int torSocksPort = 9050;
@Getter(lombok.AccessLevel.NONE)
@Setter(lombok.AccessLevel.NONE)
private int torConnectTimeout = 30000;
@Getter(lombok.AccessLevel.NONE)
@Setter(lombok.AccessLevel.NONE)
private int torReadTimeout = 30000;
@Getter(lombok.AccessLevel.NONE)
@Setter(lombok.AccessLevel.NONE)
private int torBroadcastCount = 2;
@Getter(lombok.AccessLevel.NONE)
@Setter(lombok.AccessLevel.NONE)
private boolean torCircuitIsolation = true;
@Getter(lombok.AccessLevel.NONE)
@Setter(lombok.AccessLevel.NONE)
private int torControlPort = 0;
@Getter(lombok.AccessLevel.NONE)
@Setter(lombok.AccessLevel.NONE)
private String torControlPassword = "";

public boolean isTorBroadcastEnable() {
return torBroadcastEnable;
}

public String getTorSocksHost() {
return torSocksHost;
}

public int getTorSocksPort() {
return torSocksPort;
}

public int getTorConnectTimeout() {
return torConnectTimeout;
}

public int getTorReadTimeout() {
return torReadTimeout;
}

public int getTorBroadcastCount() {
return torBroadcastCount;
}

public boolean isTorCircuitIsolation() {
return torCircuitIsolation;
}

public int getTorControlPort() {
return torControlPort;
}

public String getTorControlPassword() {
return torControlPassword;
}

// ---- Sub-object fields ----
private P2pConfig p2p = new P2pConfig();
private HttpConfig http = new HttpConfig();
Expand Down Expand Up @@ -394,6 +461,17 @@ public static NodeConfig fromConfig(Config config) {
+ "Please use [node.allowShieldedTransactionApi] instead.");
}

// node.tor.* — read manually so an absent block is a no-op (feature stays off)
nc.torBroadcastEnable = getBool(section, "tor.enabled", false);
nc.torSocksHost = getString(section, "tor.socksHost", "127.0.0.1");
nc.torSocksPort = getInt(section, "tor.socksPort", 9050);
nc.torConnectTimeout = getInt(section, "tor.connectTimeout", 30000);
nc.torReadTimeout = getInt(section, "tor.readTimeout", 30000);
nc.torBroadcastCount = getInt(section, "tor.broadcastCount", 2);
nc.torCircuitIsolation = getBool(section, "tor.circuitIsolation", true);
nc.torControlPort = getInt(section, "tor.controlPort", 0);
nc.torControlPassword = getString(section, "tor.controlPassword", "");

// node.shutdown.* — PascalCase keys (BlockTime, BlockHeight), cannot auto-bind
nc.shutdownBlockTime = config.hasPath("node.shutdown.BlockTime")
? config.getString("node.shutdown.BlockTime") : "";
Expand Down
20 changes: 19 additions & 1 deletion framework/src/main/java/org/tron/core/Wallet.java
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@
import org.tron.core.net.TronNetDelegate;
import org.tron.core.net.TronNetService;
import org.tron.core.net.message.adv.TransactionMessage;
import org.tron.core.net.service.tor.TorBroadcastService;
import org.tron.core.store.AccountIdIndexStore;
import org.tron.core.store.AccountStore;
import org.tron.core.store.AccountTraceStore;
Expand Down Expand Up @@ -277,6 +278,8 @@ public class Wallet {
@Autowired
private TronNetService tronNetService;
@Autowired
private TorBroadcastService torBroadcastService;
@Autowired
private TronNetDelegate tronNetDelegate;
@Autowired
private Manager dbManager;
Expand Down Expand Up @@ -556,9 +559,24 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) {
if (trx.getInstance().getRawData().getContractCount() == 0) {
throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST);
}
TransactionMessage message = new TransactionMessage(trx.getInstance().toByteArray());
trx.checkExpiration(chainBaseManager.getNextBlockSlotTime());
dbManager.pushTransaction(trx);

if (CommonParameter.getInstance().isTorBroadcastEnable()) {
// Anonymous path: the transaction is validated and kept locally, but instead of being
// advertised to P2P peers (which would expose this node's IP as the origin) it is relayed
// through the Tor SOCKS5 proxy to standard TRON nodes, which broadcast it to the network.
int relayed = torBroadcastService.broadcastTransaction(signedTransaction);
if (relayed == 0) {
return builder.setResult(false).setCode(response_code.NOT_ENOUGH_EFFECTIVE_CONNECTION)
.setMessage(ByteString.copyFromUtf8("Tor broadcast failed.")).build();
}
logger.info("Broadcast transaction {} via Tor to {} relay nodes successfully.",
txID, relayed);
return builder.setResult(true).setCode(response_code.SUCCESS).build();
}

TransactionMessage message = new TransactionMessage(trx.getInstance().toByteArray());
int num = tronNetService.fastBroadcastTransaction(message);
if (num == 0 && minEffectiveConnection != 0) {
return builder.setResult(false).setCode(response_code.NOT_ENOUGH_EFFECTIVE_CONNECTION)
Expand Down
11 changes: 11 additions & 0 deletions framework/src/main/java/org/tron/core/config/args/Args.java
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,17 @@ private static void applyNodeConfig(NodeConfig nc) {
PARAMETER.unsolidifiedBlockCheck = nc.isUnsolidifiedBlockCheck();
PARAMETER.maxUnsolidifiedBlocks = nc.getMaxUnsolidifiedBlocks();

// ---- Tor anonymous transaction broadcast ----
PARAMETER.torBroadcastEnable = nc.isTorBroadcastEnable();
PARAMETER.torSocksHost = nc.getTorSocksHost();
PARAMETER.torSocksPort = nc.getTorSocksPort();
PARAMETER.torConnectTimeout = nc.getTorConnectTimeout();
PARAMETER.torReadTimeout = nc.getTorReadTimeout();
PARAMETER.torBroadcastCount = nc.getTorBroadcastCount();
PARAMETER.torCircuitIsolation = nc.isTorCircuitIsolation();
PARAMETER.torControlPort = nc.getTorControlPort();
PARAMETER.torControlPassword = nc.getTorControlPassword();

// disabledApi list — lowercase normalization
PARAMETER.disabledApiList = nc.getDisabledApi().isEmpty()
? Collections.emptyList()
Expand Down
10 changes: 10 additions & 0 deletions framework/src/main/java/org/tron/core/net/TronNetService.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.tron.core.net.service.sync.SyncService;
import org.tron.p2p.P2pConfig;
import org.tron.p2p.P2pService;
import org.tron.p2p.discover.Node;
import org.tron.p2p.utils.NetUtil;

@Slf4j(topic = "net")
Expand Down Expand Up @@ -138,6 +139,15 @@ public int fastBroadcastTransaction(TransactionMessage msg) {
return advService.fastBroadcastTransaction(msg);
}

/**
* Nodes discovered via the (UDP) discovery layer. Only a subset of these is actually connected
* as sync peers; the rest are known-but-unconnected and are used as anonymous Tor broadcast
* targets (see TorBroadcastService).
*/
public List<Node> getTableNodes() {
return p2pService.getTableNodes();
}

public static boolean hasIpv4Stack(Set<String> ipSet) {
for (String ip : ipSet) {
InetAddress inetAddress;
Expand Down
Loading
Loading