support using monero native libraries (experimental)

This commit is contained in:
woodser 2024-04-01 18:41:40 -04:00
parent 53001823af
commit 01dd6a8af9
8 changed files with 204 additions and 79 deletions

View file

@ -49,7 +49,7 @@ bitcoind:
-peerbloomfilters=1 \
-datadir=.localnet/ \
-rpcuser=haveno \
-rpcpassword=1234
-rpcpassword=1234 \
btc-blocks:
./.localnet/bitcoin-cli \
@ -75,7 +75,7 @@ monerod1-local:
--add-exclusive-node 127.0.0.1:58080 \
--rpc-access-control-origins http://localhost:8080 \
--fixed-difficulty 500 \
--disable-rpc-ban
--disable-rpc-ban \
monerod2-local:
./.localnet/monerod \
@ -93,7 +93,7 @@ monerod2-local:
--add-exclusive-node 127.0.0.1:58080 \
--rpc-access-control-origins http://localhost:8080 \
--fixed-difficulty 500 \
--disable-rpc-ban
--disable-rpc-ban \
monerod3-local:
./.localnet/monerod \
@ -111,7 +111,7 @@ monerod3-local:
--add-exclusive-node 127.0.0.1:48080 \
--rpc-access-control-origins http://localhost:8080 \
--fixed-difficulty 500 \
--disable-rpc-ban
--disable-rpc-ban \
funding-wallet-stagenet:
./.localnet/monero-wallet-rpc \
@ -121,7 +121,7 @@ funding-wallet-stagenet:
--rpc-access-control-origins http://localhost:8080 \
--wallet-dir ./.localnet \
--daemon-ssl-allow-any-cert \
--daemon-address http://127.0.0.1:38081
--daemon-address http://127.0.0.1:38081 \
#--proxy 127.0.0.1:49775 \
@ -132,7 +132,7 @@ funding-wallet-local:
--rpc-bind-port 28084 \
--rpc-login rpc_user:abc123 \
--rpc-access-control-origins http://localhost:8080 \
--wallet-dir ./.localnet
--wallet-dir ./.localnet \
# use .bat extension for windows binaries
APP_EXT :=
@ -168,7 +168,8 @@ arbitrator-daemon-local:
--appName=haveno-XMR_LOCAL_arbitrator \
--apiPassword=apitest \
--apiPort=9998 \
--passwordRequired=false
--passwordRequired=false \
--useNativeXmrWallet=false \
arbitrator-desktop-local:
# Arbitrator needs to be registered before making trades
@ -179,7 +180,8 @@ arbitrator-desktop-local:
--nodePort=4444 \
--appName=haveno-XMR_LOCAL_arbitrator \
--apiPassword=apitest \
--apiPort=9998
--apiPort=9998 \
--useNativeXmrWallet=false \
arbitrator2-daemon-local:
# Arbitrator needs to be registered before making trades
@ -190,7 +192,8 @@ arbitrator2-daemon-local:
--nodePort=7777 \
--appName=haveno-XMR_LOCAL_arbitrator2 \
--apiPassword=apitest \
--apiPort=10001
--apiPort=10001 \
--useNativeXmrWallet=false \
arbitrator2-desktop-local:
# Arbitrator needs to be registered before making trades
@ -201,7 +204,8 @@ arbitrator2-desktop-local:
--nodePort=7777 \
--appName=haveno-XMR_LOCAL_arbitrator2 \
--apiPassword=apitest \
--apiPort=10001
--apiPort=10001 \
--useNativeXmrWallet=false \
user1-daemon-local:
./haveno-daemon$(APP_EXT) \
@ -213,7 +217,8 @@ user1-daemon-local:
--apiPassword=apitest \
--apiPort=9999 \
--walletRpcBindPort=38091 \
--passwordRequired=false
--passwordRequired=false \
--useNativeXmrWallet=false \
user1-desktop-local:
./haveno-desktop$(APP_EXT) \
@ -225,7 +230,8 @@ user1-desktop-local:
--apiPassword=apitest \
--apiPort=9999 \
--walletRpcBindPort=38091 \
--logLevel=info
--logLevel=info \
--useNativeXmrWallet=false \
user2-desktop-local:
./haveno-desktop$(APP_EXT) \
@ -236,7 +242,8 @@ user2-desktop-local:
--appName=haveno-XMR_LOCAL_user2 \
--apiPassword=apitest \
--apiPort=10000 \
--walletRpcBindPort=38092
--walletRpcBindPort=38092 \
--useNativeXmrWallet=false \
user2-daemon-local:
./haveno-daemon$(APP_EXT) \
@ -248,7 +255,8 @@ user2-daemon-local:
--apiPassword=apitest \
--apiPort=10000 \
--walletRpcBindPort=38092 \
--passwordRequired=false
--passwordRequired=false \
--useNativeXmrWallet=false \
user3-desktop-local:
./haveno-desktop$(APP_EXT) \
@ -259,7 +267,8 @@ user3-desktop-local:
--appName=haveno-XMR_LOCAL_user3 \
--apiPassword=apitest \
--apiPort=10002 \
--walletRpcBindPort=38093
--walletRpcBindPort=38093 \
--useNativeXmrWallet=false \
user3-daemon-local:
./haveno-daemon$(APP_EXT) \
@ -271,7 +280,8 @@ user3-daemon-local:
--apiPassword=apitest \
--apiPort=10002 \
--walletRpcBindPort=38093 \
--passwordRequired=false
--passwordRequired=false \
--useNativeXmrWallet=false \
# Stagenet network
@ -288,7 +298,7 @@ monerod-stagenet-custom:
--p2p-bind-port 39080 \
--rpc-bind-port 39081 \
--bootstrap-daemon-address auto \
--rpc-access-control-origins http://localhost:8080
--rpc-access-control-origins http://localhost:8080 \
seednode-stagenet:
./haveno-seednode$(APP_EXT) \
@ -297,7 +307,7 @@ seednode-stagenet:
--useDevPrivilegeKeys=false \
--nodePort=9999 \
--appName=haveno-XMR_STAGENET_Seed_3002 \
--xmrNode=http://127.0.0.1:38081
--xmrNode=http://127.0.0.1:38081 \
seednode2-stagenet:
./haveno-seednode$(APP_EXT) \
@ -306,7 +316,7 @@ seednode2-stagenet:
--useDevPrivilegeKeys=false \
--nodePort=9999 \
--appName=haveno-XMR_STAGENET_Seed_3003 \
--xmrNode=http://127.0.0.1:38081
--xmrNode=http://127.0.0.1:38081 \
arbitrator-daemon-stagenet:
# Arbitrator needs to be registered before making trades
@ -319,7 +329,8 @@ arbitrator-daemon-stagenet:
--apiPassword=apitest \
--apiPort=3200 \
--passwordRequired=false \
--xmrNode=http://127.0.0.1:38081
--xmrNode=http://127.0.0.1:38081 \
--useNativeXmrWallet=false \
# Arbitrator needs to be registered before making trades
arbitrator-desktop-stagenet:
@ -331,7 +342,8 @@ arbitrator-desktop-stagenet:
--appName=haveno-XMR_STAGENET_arbitrator \
--apiPassword=apitest \
--apiPort=3200 \
--xmrNode=http://127.0.0.1:38081
--xmrNode=http://127.0.0.1:38081 \
--useNativeXmrWallet=false \
user1-daemon-stagenet:
./haveno-daemon$(APP_EXT) \
@ -342,7 +354,8 @@ user1-daemon-stagenet:
--appName=haveno-XMR_STAGENET_user1 \
--apiPassword=apitest \
--apiPort=3201 \
--passwordRequired=false
--passwordRequired=false \
--useNativeXmrWallet=false \
user1-desktop-stagenet:
./haveno-desktop$(APP_EXT) \
@ -352,7 +365,8 @@ user1-desktop-stagenet:
--nodePort=9999 \
--appName=haveno-XMR_STAGENET_user1 \
--apiPassword=apitest \
--apiPort=3201
--apiPort=3201 \
--useNativeXmrWallet=false \
user2-daemon-stagenet:
./haveno-daemon$(APP_EXT) \
@ -363,7 +377,8 @@ user2-daemon-stagenet:
--appName=haveno-XMR_STAGENET_user2 \
--apiPassword=apitest \
--apiPort=3202 \
--passwordRequired=false
--passwordRequired=false \
--useNativeXmrWallet=false \
user2-desktop-stagenet:
./haveno-desktop$(APP_EXT) \
@ -373,7 +388,8 @@ user2-desktop-stagenet:
--nodePort=9999 \
--appName=haveno-XMR_STAGENET_user2 \
--apiPassword=apitest \
--apiPort=3202
--apiPort=3202 \
--useNativeXmrWallet=false \
user3-desktop-stagenet:
./haveno-desktop$(APP_EXT) \
@ -383,7 +399,8 @@ user3-desktop-stagenet:
--nodePort=9999 \
--appName=haveno-XMR_STAGENET_user3 \
--apiPassword=apitest \
--apiPort=3203
--apiPort=3203 \
--useNativeXmrWallet=false \
haveno-desktop-stagenet:
./haveno-desktop$(APP_EXT) \
@ -393,7 +410,8 @@ haveno-desktop-stagenet:
--nodePort=9999 \
--appName=Haveno \
--apiPassword=apitest \
--apiPort=3204
--apiPort=3204 \
--useNativeXmrWallet=false \
# Mainnet network
@ -409,7 +427,7 @@ seednode:
--useDevPrivilegeKeys=false \
--nodePort=9999 \
--appName=haveno-XMR_MAINNET_Seed_1002 \
--xmrNode=http://127.0.0.1:18081
--xmrNode=http://127.0.0.1:18081 \
seednode2:
./haveno-seednode$(APP_EXT) \
@ -418,7 +436,7 @@ seednode2:
--useDevPrivilegeKeys=false \
--nodePort=9999 \
--appName=haveno-XMR_MAINNET_Seed_1003 \
--xmrNode=http://127.0.0.1:18081
--xmrNode=http://127.0.0.1:18081 \
arbitrator-daemon:
# Arbitrator needs to be registered before making trades
@ -431,7 +449,8 @@ arbitrator-daemon:
--apiPassword=apitest \
--apiPort=1200 \
--passwordRequired=false \
--xmrNode=http://127.0.0.1:18081
--xmrNode=http://127.0.0.1:18081 \
--useNativeXmrWallet=false \
# Arbitrator needs to be registered before making trades
arbitrator-desktop:
@ -443,7 +462,8 @@ arbitrator-desktop:
--appName=haveno-XMR_MAINNET_arbitrator \
--apiPassword=apitest \
--apiPort=1200 \
--xmrNode=http://127.0.0.1:18081
--xmrNode=http://127.0.0.1:18081 \
--useNativeXmrWallet=false \
user1-daemon:
./haveno-daemon$(APP_EXT) \
@ -454,7 +474,8 @@ user1-daemon:
--appName=haveno-XMR_MAINNET_user1 \
--apiPassword=apitest \
--apiPort=1201 \
--passwordRequired=false
--passwordRequired=false \
--useNativeXmrWallet=false \
user1-desktop:
./haveno-desktop$(APP_EXT) \
@ -464,7 +485,8 @@ user1-desktop:
--nodePort=9999 \
--appName=haveno-XMR_MAINNET_user1 \
--apiPassword=apitest \
--apiPort=1201
--apiPort=1201 \
--useNativeXmrWallet=false \
user2-daemon:
./haveno-daemon$(APP_EXT) \
@ -475,7 +497,8 @@ user2-daemon:
--appName=haveno-XMR_MAINNET_user2 \
--apiPassword=apitest \
--apiPort=1202 \
--passwordRequired=false
--passwordRequired=false \
--useNativeXmrWallet=false \
user2-desktop:
./haveno-desktop$(APP_EXT) \
@ -485,7 +508,8 @@ user2-desktop:
--nodePort=9999 \
--appName=haveno-XMR_MAINNET_user2 \
--apiPassword=apitest \
--apiPort=1202
--apiPort=1202 \
--useNativeXmrWallet=false \
user3-desktop:
./haveno-desktop$(APP_EXT) \
@ -495,4 +519,5 @@ user3-desktop:
--nodePort=9999 \
--appName=haveno-XMR_MAINNET_user3 \
--apiPassword=apitest \
--apiPort=1203
--apiPort=1203 \
--useNativeXmrWallet=false \

View file

@ -49,7 +49,7 @@ configure(subprojects) {
gsonVersion = '2.8.5'
guavaVersion = '32.1.1-jre'
guiceVersion = '7.0.0'
moneroJavaVersion = '0.8.11'
moneroJavaVersion = '0.8.21'
httpclient5Version = '5.0'
hamcrestVersion = '2.2'
httpclientVersion = '4.5.12'

View file

@ -100,6 +100,7 @@ public class Config {
public static final String XMR_NODE_USERNAME = "xmrNodeUsername";
public static final String XMR_NODE_PASSWORD = "xmrNodePassword";
public static final String XMR_NODES = "xmrNodes";
public static final String USE_NATIVE_XMR_WALLET = "useNativeXmrWallet";
public static final String SOCKS5_DISCOVER_MODE = "socks5DiscoverMode";
public static final String USE_ALL_PROVIDED_NODES = "useAllProvidedNodes";
public static final String USER_AGENT = "userAgent";
@ -188,6 +189,7 @@ public class Config {
public final String xmrNodeUsername;
public final String xmrNodePassword;
public final String xmrNodes;
public final boolean useNativeXmrWallet;
public final UseTorForXmr useTorForXmr;
public final boolean useTorForXmrOptionSetExplicitly;
public final String socks5DiscoverMode;
@ -532,6 +534,12 @@ public class Config {
.describedAs("ip[,...]")
.defaultsTo("");
ArgumentAcceptingOptionSpec<Boolean> useNativeXmrWalletOpt =
parser.accepts(USE_NATIVE_XMR_WALLET, "Use native wallet libraries instead of monero-wallet-rpc server")
.withRequiredArg()
.ofType(boolean.class)
.defaultsTo(false);
//noinspection rawtypes
ArgumentAcceptingOptionSpec<Enum> useTorForXmrOpt =
parser.accepts(USE_TOR_FOR_XMR, "Configure TOR for Monero connections, one of: after_sync, off, or on.")
@ -702,6 +710,7 @@ public class Config {
this.xmrNodeUsername = options.valueOf(xmrNodeUsernameOpt);
this.xmrNodePassword = options.valueOf(xmrNodePasswordOpt);
this.xmrNodes = options.valueOf(xmrNodesOpt);
this.useNativeXmrWallet = options.valueOf(useNativeXmrWalletOpt);
this.useTorForXmr = (UseTorForXmr) options.valueOf(useTorForXmrOpt);
this.useTorForXmrOptionSetExplicitly = options.has(useTorForXmrOpt);
this.socks5DiscoverMode = options.valueOf(socks5DiscoverModeOpt);

View file

@ -25,6 +25,8 @@ import haveno.core.trade.HavenoUtils;
import haveno.core.user.Preferences;
import haveno.core.xmr.XmrNodeSettings;
import haveno.core.xmr.nodes.XmrNodes;
import haveno.core.xmr.wallet.XmrWalletService;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@ -44,10 +46,9 @@ public class XmrLocalNode {
// constants
public static final long REFRESH_PERIOD_LOCAL_MS = 5000; // refresh period for local node
public static final String MONEROD_DIR = Config.baseCurrencyNetwork() == BaseCurrencyNetwork.XMR_LOCAL ? System.getProperty("user.dir") + File.separator + ".localnet" : Config.appDataDir().getAbsolutePath();
public static final String MONEROD_NAME = Utilities.isWindows() ? "monerod.exe" : "monerod";
public static final String MONEROD_PATH = MONEROD_DIR + File.separator + MONEROD_NAME;
private static final String MONEROD_DATADIR = Config.baseCurrencyNetwork() == BaseCurrencyNetwork.XMR_LOCAL ? MONEROD_DIR + File.separator + Config.baseCurrencyNetwork().toString().toLowerCase() + File.separator + "node1" : null; // use default directory unless local
public static final String MONEROD_PATH = XmrWalletService.MONERO_BINS_DIR + File.separator + MONEROD_NAME;
private static final String MONEROD_DATADIR = Config.baseCurrencyNetwork() == BaseCurrencyNetwork.XMR_LOCAL ? XmrWalletService.MONERO_BINS_DIR + File.separator + Config.baseCurrencyNetwork().toString().toLowerCase() + File.separator + "node1" : null; // use default directory unless local
// instance fields
private MoneroDaemonRpc daemon;

View file

@ -357,6 +357,8 @@ public class HavenoSetup {
private void maybeInstallDependencies() {
try {
// install monerod
File monerodFile = new File(XmrLocalNode.MONEROD_PATH);
String monerodResourcePath = "bin/" + XmrLocalNode.MONEROD_NAME;
if (!monerodFile.exists() || !FileUtil.resourceEqualToFile(monerodResourcePath, monerodFile)) {
@ -366,13 +368,14 @@ public class HavenoSetup {
monerodFile.setExecutable(true);
}
File moneroWalletFile = new File(XmrWalletService.MONERO_WALLET_RPC_PATH);
String moneroWalletResourcePath = "bin/" + XmrWalletService.MONERO_WALLET_RPC_NAME;
if (!moneroWalletFile.exists() || !FileUtil.resourceEqualToFile(moneroWalletResourcePath, moneroWalletFile)) {
// install monero-wallet-rpc
File moneroWalletRpcFile = new File(XmrWalletService.MONERO_WALLET_RPC_PATH);
String moneroWalletRpcResourcePath = "bin/" + XmrWalletService.MONERO_WALLET_RPC_NAME;
if (!moneroWalletRpcFile.exists() || !FileUtil.resourceEqualToFile(moneroWalletRpcResourcePath, moneroWalletRpcFile)) {
log.info("Installing monero-wallet-rpc");
moneroWalletFile.getParentFile().mkdirs();
FileUtil.resourceToFile(moneroWalletResourcePath, moneroWalletFile);
moneroWalletFile.setExecutable(true);
moneroWalletRpcFile.getParentFile().mkdirs();
FileUtil.resourceToFile(moneroWalletRpcResourcePath, moneroWalletRpcFile);
moneroWalletRpcFile.setExecutable(true);
}
} catch (Exception e) {
e.printStackTrace();

View file

@ -92,6 +92,7 @@ public class XmrModule extends AppModule {
bindConstant().annotatedWith(named(Config.XMR_NODE_USERNAME)).to(config.xmrNodeUsername);
bindConstant().annotatedWith(named(Config.XMR_NODE_PASSWORD)).to(config.xmrNodePassword);
bindConstant().annotatedWith(named(Config.XMR_NODES)).to(config.xmrNodes);
bindConstant().annotatedWith(named(Config.USE_NATIVE_XMR_WALLET)).to(config.useNativeXmrWallet);
bindConstant().annotatedWith(named(Config.USER_AGENT)).to(config.userAgent);
bindConstant().annotatedWith(named(Config.NUM_CONNECTIONS_FOR_BTC)).to(config.numConnectionsForBtc);
bindConstant().annotatedWith(named(Config.USE_ALL_PROVIDED_NODES)).to(config.useAllProvidedNodes);

View file

@ -85,6 +85,7 @@ import monero.daemon.model.MoneroOutput;
import monero.daemon.model.MoneroSubmitTxResult;
import monero.daemon.model.MoneroTx;
import monero.wallet.MoneroWallet;
import monero.wallet.MoneroWalletFull;
import monero.wallet.MoneroWalletRpc;
import monero.wallet.model.MoneroCheckTx;
import monero.wallet.model.MoneroDestination;
@ -108,11 +109,11 @@ import org.slf4j.LoggerFactory;
public class XmrWalletService {
private static final Logger log = LoggerFactory.getLogger(XmrWalletService.class);
// Monero configuration
// monero configuration
public static final int NUM_BLOCKS_UNLOCK = 10;
public static final String MONERO_WALLET_RPC_DIR = Config.baseCurrencyNetwork().isTestnet() ? System.getProperty("user.dir") + File.separator + ".localnet" : Config.appDataDir().getAbsolutePath(); // .localnet contains monero-wallet-rpc and wallet files
public static final String MONERO_BINS_DIR = Config.baseCurrencyNetwork().isTestnet() ? System.getProperty("user.dir") + File.separator + ".localnet" : Config.appDataDir().getAbsolutePath(); // .localnet contains monero binaries and wallet files
public static final String MONERO_WALLET_RPC_NAME = Utilities.isWindows() ? "monero-wallet-rpc.exe" : "monero-wallet-rpc";
public static final String MONERO_WALLET_RPC_PATH = MONERO_WALLET_RPC_DIR + File.separator + MONERO_WALLET_RPC_NAME;
public static final String MONERO_WALLET_RPC_PATH = MONERO_BINS_DIR + File.separator + MONERO_WALLET_RPC_NAME;
public static final double MINER_FEE_TOLERANCE = 0.25; // miner fee must be within percent of estimated fee
public static final MoneroTxPriority PROTOCOL_FEE_PRIORITY = MoneroTxPriority.ELEVATED;
private static final MoneroNetworkType MONERO_NETWORK_TYPE = getMoneroNetworkType();
@ -123,7 +124,7 @@ public class XmrWalletService {
private static final String KEYS_FILE_POSTFIX = ".keys";
private static final String ADDRESS_FILE_POSTFIX = ".address.txt";
private static final int NUM_MAX_WALLET_BACKUPS = 1;
private static final int MONERO_LOG_LEVEL = 0;
private static final int MONERO_LOG_LEVEL = -1; // monero library log level, -1 to disable
private static final int MAX_SYNC_ATTEMPTS = 3;
private static final boolean PRINT_STACK_TRACE = false;
private static final String THREAD_ID = XmrWalletService.class.getSimpleName();
@ -140,12 +141,13 @@ public class XmrWalletService {
private final File walletDir;
private final File xmrWalletFile;
private final int rpcBindPort;
private final boolean useNativeXmrWallet;
protected final CopyOnWriteArraySet<XmrBalanceListener> balanceListeners = new CopyOnWriteArraySet<>();
protected final CopyOnWriteArraySet<MoneroWalletListenerI> walletListeners = new CopyOnWriteArraySet<>();
private ChangeListener<? super Number> walletInitListener;
private TradeManager tradeManager;
private MoneroWalletRpc wallet;
private MoneroWallet wallet;
private Object walletLock = new Object();
private boolean wasWalletSynced = false;
private final Map<String, Optional<MoneroTx>> txCache = new HashMap<String, Optional<MoneroTx>>();
@ -158,6 +160,7 @@ public class XmrWalletService {
private List<MoneroSubaddress> cachedSubaddresses;
private List<MoneroTxWallet> cachedTxs;
@SuppressWarnings("unused")
@Inject
XmrWalletService(User user,
Preferences preferences,
@ -166,7 +169,8 @@ public class XmrWalletService {
WalletsSetup walletsSetup,
XmrAddressEntryList xmrAddressEntryList,
@Named(Config.WALLET_DIR) File walletDir,
@Named(Config.WALLET_RPC_BIND_PORT) int rpcBindPort) {
@Named(Config.WALLET_RPC_BIND_PORT) int rpcBindPort,
@Named(Config.USE_NATIVE_XMR_WALLET) boolean useNativeXmrWallet) {
this.user = user;
this.preferences = preferences;
this.accountService = accountService;
@ -175,10 +179,11 @@ public class XmrWalletService {
this.xmrAddressEntryList = xmrAddressEntryList;
this.walletDir = walletDir;
this.rpcBindPort = rpcBindPort;
this.useNativeXmrWallet = useNativeXmrWallet;
this.xmrWalletFile = new File(walletDir, MONERO_WALLET_NAME);
// set monero logging
MoneroUtils.setLogLevel(MONERO_LOG_LEVEL);
if (MONERO_LOG_LEVEL >= 0) MoneroUtils.setLogLevel(MONERO_LOG_LEVEL);
// initialize after account open and basic setup
walletsSetup.addSetupTaskHandler(() -> { // TODO: use something better than legacy WalletSetup for notification to initialize
@ -311,23 +316,37 @@ public class XmrWalletService {
return new File(path + KEYS_FILE_POSTFIX).exists();
}
public MoneroWalletRpc createWallet(String walletName) {
log.info("{}.createWallet({})", getClass().getSimpleName(), walletName);
if (isShutDownStarted) throw new IllegalStateException("Cannot create wallet because shutting down");
return createWalletRpc(new MoneroWalletConfig()
.setPath(walletName)
.setPassword(getWalletPassword()),
null);
public MoneroWallet createWallet(String walletName) {
return createWallet(walletName, null);
}
public MoneroWalletRpc openWallet(String walletName, boolean applyProxyUri) {
public MoneroWallet createWallet(String walletName, Integer walletRpcPort) {
log.info("{}.createWallet({})", getClass().getSimpleName(), walletName);
if (isShutDownStarted) throw new IllegalStateException("Cannot create wallet because shutting down");
MoneroWalletConfig config = getWalletConfig(walletName);
return isNativeLibraryApplied() ? createWalletFull(config) : createWalletRpc(config, walletRpcPort);
}
public MoneroWallet openWallet(String walletName, boolean applyProxyUri) {
return openWallet(walletName, null, applyProxyUri);
}
public MoneroWallet openWallet(String walletName, Integer walletRpcPort, boolean applyProxyUri) {
log.info("{}.openWallet({})", getClass().getSimpleName(), walletName);
if (isShutDownStarted) throw new IllegalStateException("Cannot open wallet because shutting down");
return openWalletRpc(new MoneroWalletConfig()
.setPath(walletName)
.setPassword(getWalletPassword()),
null,
applyProxyUri);
MoneroWalletConfig config = getWalletConfig(walletName);
return isNativeLibraryApplied() ? openWalletFull(config, applyProxyUri) : openWalletRpc(config, walletRpcPort, applyProxyUri);
}
private MoneroWalletConfig getWalletConfig(String walletName) {
String walletConfigPath = (isNativeLibraryApplied() ? walletDir.getPath() + File.separator : "") + walletName;
MoneroWalletConfig config = new MoneroWalletConfig().setPath(walletConfigPath).setPassword(getWalletPassword());
if (isNativeLibraryApplied()) config.setNetworkType(getMoneroNetworkType());
return config;
}
private boolean isNativeLibraryApplied() {
return useNativeXmrWallet && MoneroUtils.isNativeLibraryLoaded();
}
/**
@ -377,8 +396,12 @@ public class XmrWalletService {
}
public void stopWallet(MoneroWallet wallet, String path, boolean force) {
// only wallet rpc process needs stopped
if (wallet instanceof MoneroWalletRpc) {
MONERO_WALLET_RPC_MANAGER.stopInstance((MoneroWalletRpc) wallet, path, force);
}
}
public void deleteWallet(String walletName) {
log.info("{}.deleteWallet({})", getClass().getSimpleName(), walletName);
@ -805,6 +828,18 @@ public class XmrWalletService {
walletInitListener = (obs, oldVal, newVal) -> initMainWalletIfConnected();
xmrConnectionService.downloadPercentageProperty().addListener(walletInitListener);
initMainWalletIfConnected();
// try to load native monero library
if (useNativeXmrWallet && !MoneroUtils.isNativeLibraryLoaded()) {
try {
MoneroUtils.loadNativeLibrary();
} catch (Exception | UnsatisfiedLinkError e) {
log.warn("Failed to load Monero native libraries: " + e.getMessage());
}
}
String appliedMsg = "Monero native libraries applied: " + isNativeLibraryApplied();
if (useNativeXmrWallet && !isNativeLibraryApplied()) log.warn(appliedMsg);
else log.info(appliedMsg);
}
private void initMainWalletIfConnected() {
@ -823,6 +858,7 @@ public class XmrWalletService {
}
private void maybeInitMainWallet(boolean sync, int numAttempts) {
synchronized (walletLock) {
if (isShutDownStarted) return;
@ -830,11 +866,10 @@ public class XmrWalletService {
if (wallet == null) {
MoneroDaemonRpc daemon = xmrConnectionService.getDaemon();
log.info("Initializing main wallet with monerod=" + (daemon == null ? "null" : daemon.getRpcConnection().getUri()));
MoneroWalletConfig walletConfig = new MoneroWalletConfig().setPath(MONERO_WALLET_NAME).setPassword(getWalletPassword());
if (MoneroUtils.walletExists(xmrWalletFile.getPath())) {
wallet = openWalletRpc(walletConfig, rpcBindPort, isProxyApplied(wasWalletSynced));
wallet = openWallet(MONERO_WALLET_NAME, rpcBindPort, isProxyApplied(wasWalletSynced));
} else if (xmrConnectionService.getConnection() != null && Boolean.TRUE.equals(xmrConnectionService.getConnection().isConnected())) {
wallet = createWalletRpc(walletConfig, rpcBindPort);
wallet = createWallet(MONERO_WALLET_NAME, rpcBindPort);
// set wallet creation date to yesterday to guarantee complete restore
LocalDateTime localDateTime = LocalDate.now().atStartOfDay().minusDays(1);
@ -845,7 +880,7 @@ public class XmrWalletService {
// sync wallet and register listener
if (wallet != null && !isShutDownStarted) {
log.info("Monero wallet uri={}, path={}", wallet.getRpcConnection().getUri(), wallet.getPath());
log.info("Monero wallet path={}", wallet.getPath());
// sync main wallet if applicable
if (sync && numAttempts > 0) {
@ -946,6 +981,53 @@ public class XmrWalletService {
});
}
private MoneroWalletFull createWalletFull(MoneroWalletConfig config) {
// must be connected to daemon
MoneroRpcConnection connection = xmrConnectionService.getConnection();
if (connection == null || !Boolean.TRUE.equals(connection.isConnected())) throw new RuntimeException("Must be connected to daemon before creating wallet");
// create wallet
MoneroWalletFull walletFull = null;
try {
// create wallet
log.info("Creating full wallet " + config.getPath() + " connected to daemon " + connection.getUri());
long time = System.currentTimeMillis();
config.setServer(connection);
walletFull = MoneroWalletFull.createWallet(config);
walletFull.getDaemonConnection().setPrintStackTrace(PRINT_STACK_TRACE);
log.info("Done creating full wallet " + config.getPath() + " in " + (System.currentTimeMillis() - time) + " ms");
return walletFull;
} catch (Exception e) {
e.printStackTrace();
if (walletFull != null) stopWallet(walletFull, config.getPath());
throw new IllegalStateException("Could not create wallet '" + config.getPath() + "'");
}
}
private MoneroWalletFull openWalletFull(MoneroWalletConfig config, boolean applyProxyUri) {
MoneroWalletFull walletFull = null;
try {
// configure connection
MoneroRpcConnection connection = new MoneroRpcConnection(xmrConnectionService.getConnection());
if (!applyProxyUri) connection.setProxyUri(null);
// open wallet
config.setNetworkType(getMoneroNetworkType());
config.setServer(connection);
walletFull = MoneroWalletFull.openWallet(config);
if (walletFull.getDaemonConnection() != null) walletFull.getDaemonConnection().setPrintStackTrace(PRINT_STACK_TRACE);
log.info("Done opening full wallet " + config.getPath());
return walletFull;
} catch (Exception e) {
e.printStackTrace();
if (walletFull != null) stopWallet(walletFull, config.getPath());
throw new IllegalStateException("Could not open full wallet '" + config.getPath() + "'");
}
}
private MoneroWalletRpc createWalletRpc(MoneroWalletConfig config, Integer port) {
// must be connected to daemon
@ -964,11 +1046,12 @@ public class XmrWalletService {
walletRpc.stopSyncing();
// create wallet
log.info("Creating wallet " + config.getPath() + " connected to daemon " + connection.getUri());
log.info("Creating RPC wallet " + config.getPath() + " connected to daemon " + connection.getUri());
long time = System.currentTimeMillis();
walletRpc.createWallet(config.setServer(connection));
config.setServer(connection);
walletRpc.createWallet(config);
walletRpc.getDaemonConnection().setPrintStackTrace(PRINT_STACK_TRACE);
log.info("Done creating wallet " + config.getPath() + " in " + (System.currentTimeMillis() - time) + " ms");
log.info("Done creating RPC wallet " + config.getPath() + " in " + (System.currentTimeMillis() - time) + " ms");
return walletRpc;
} catch (Exception e) {
e.printStackTrace();
@ -993,9 +1076,11 @@ public class XmrWalletService {
if (!applyProxyUri) connection.setProxyUri(null);
// open wallet
walletRpc.openWallet(config.setServer(connection));
log.info("Opening RPC wallet " + config.getPath() + " connected to daemon " + connection.getUri());
config.setServer(connection);
walletRpc.openWallet(config);
if (walletRpc.getDaemonConnection() != null) walletRpc.getDaemonConnection().setPrintStackTrace(PRINT_STACK_TRACE);
log.info("Done opening wallet " + config.getPath());
log.info("Done opening RPC wallet " + config.getPath());
return walletRpc;
} catch (Exception e) {
e.printStackTrace();
@ -1060,6 +1145,7 @@ public class XmrWalletService {
maybeInitMainWallet(false);
} else {
wallet.setDaemonConnection(connection);
wallet.setProxyUri(connection.getProxyUri());
}
// sync wallet on new thread

View file

@ -886,9 +886,9 @@
<sha256 value="c92e2ca40a3f2474d61e56831aeb379cf8ae3dddeea61b4a828cee2d99f71f38" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.github.woodser" name="monero-java" version="0.8.11">
<artifact name="monero-java-0.8.11.jar">
<sha256 value="37c125a31463c44e43452bc3e18e74a05b65d1fbebb11adc5131521b29b48a6b" origin="Generated by Gradle"/>
<component group="io.github.woodser" name="monero-java" version="0.8.21">
<artifact name="monero-java-0.8.21.jar">
<sha256 value="6389baa853abcbeaa4949ef798f0705d074b1af1a72466cafcb1fb8efbd4e398" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.grpc" name="grpc-api" version="1.42.1">