Skip to content
Merged
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
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ jobs:
echo "static closure symbols are exported"; exit 1
fi
mkdir -p test_wallets
mvn -B test -Dmaven.test.skip=false -Dtest=TestMoneroUtils,TestNativeLibrary -DargLine=-Djava.library.path=build
mvn -B test -Dmaven.test.skip=false -Dtest=TestMoneroUtils,TestNativeLibrary,TestSerialization,TestMoneroConnectionManager#testResponseTimesAfterSettingChange -DargLine=-Djava.library.path=build

- name: Upload monero-java library
uses: actions/upload-artifact@v7
Expand Down Expand Up @@ -288,7 +288,7 @@ jobs:
MAVEN_OPTS: -Djava.library.path=build
run: |
mkdir -p test_wallets
mvn -B test -Dmaven.test.skip=false -Dtest=TestMoneroUtils,TestNativeLibrary -DargLine=-Djava.library.path=build
mvn -B test -Dmaven.test.skip=false -Dtest=TestMoneroUtils,TestNativeLibrary,TestSerialization,TestMoneroConnectionManager#testResponseTimesAfterSettingChange -DargLine=-Djava.library.path=build

- name: Upload monero-java library
uses: actions/upload-artifact@v7
Expand Down Expand Up @@ -398,7 +398,7 @@ jobs:
echo "unexpected exports above"; exit 1
fi
mkdir -p test_wallets
mvn -B test -Dmaven.test.skip=false -Dtest=TestMoneroUtils,TestNativeLibrary -DargLine=-Djava.library.path=build
mvn -B test -Dmaven.test.skip=false -Dtest=TestMoneroUtils,TestNativeLibrary,TestSerialization,TestMoneroConnectionManager#testResponseTimesAfterSettingChange -DargLine=-Djava.library.path=build

- name: Upload monero-java library
uses: actions/upload-artifact@v7
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,15 @@ walletFull.close(true);

#### For Gradle, add to build.gradle:

`compile 'io.github.woodser:monero-java:0.8.58'`
`compile 'io.github.woodser:monero-java:0.8.59'`

#### For Maven, add to pom.xml:

```xml
<dependency>
<groupId>io.github.woodser</groupId>
<artifactId>monero-java</artifactId>
<version>0.8.58</version>
<version>0.8.59</version>
</dependency>
```

Expand Down
4 changes: 3 additions & 1 deletion docs/javadocs/index-files/index-18.html
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,9 @@ <h2 class="title" id="I:S">S</h2>
<dt><a href="../monero/wallet/MoneroWalletRpc.html#setDaemonConnection(monero.common.MoneroRpcConnection,java.lang.Boolean)" class="member-name-link">setDaemonConnection(MoneroRpcConnection, Boolean)</a> - Method in class monero.wallet.<a href="../monero/wallet/MoneroWalletRpc.html" title="class in monero.wallet">MoneroWalletRpc</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../monero/wallet/MoneroWalletRpc.html#setDaemonConnection(monero.common.MoneroRpcConnection,java.lang.Boolean,monero.common.SslOptions)" class="member-name-link">setDaemonConnection(MoneroRpcConnection, Boolean, SslOptions)</a> - Method in class monero.wallet.<a href="../monero/wallet/MoneroWalletRpc.html" title="class in monero.wallet">MoneroWalletRpc</a></dt>
<dd>&nbsp;</dd>
<dd>
<div class="block">Explicit SSL options take precedence over the connection's verification setting.</div>
</dd>
<dt><a href="../monero/daemon/model/MoneroDaemonInfo.html#setDatabaseSize(java.lang.Long)" class="member-name-link">setDatabaseSize(Long)</a> - Method in class monero.daemon.model.<a href="../monero/daemon/model/MoneroDaemonInfo.html" title="class in monero.daemon.model">MoneroDaemonInfo</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../monero/daemon/model/MoneroBlock.html#setDepth(java.lang.Long)" class="member-name-link">setDepth(Long)</a> - Method in class monero.daemon.model.<a href="../monero/daemon/model/MoneroBlock.html" title="class in monero.daemon.model">MoneroBlock</a></dt>
Expand Down
2 changes: 2 additions & 0 deletions docs/javadocs/monero/common/MoneroRpcConnection.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ <h1 title="Class MoneroRpcConnection" class="title">Class MoneroRpcConnection</h
<div class="type-signature"><span class="modifiers">public class </span><span class="element-name type-name-label">MoneroRpcConnection</span>
<span class="extends-implements">extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html" title="class or interface in java.lang" class="external-link">Object</a></span></div>
<div class="block">Maintains a connection and sends requests to a Monero RPC API.
Equality compares URI, credentials, proxy, ZMQ URI, and TLS verification.
Do not mutate these settings while using a connection as a hash key.

TODO: refactor MoneroRpcConnection extends MoneroConnection?</div>
</section>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,9 @@ <h2>Uses of <a href="../MoneroRpcConnection.html" title="class in monero.common"
<div class="col-second even-row-color"><span class="type-name-label">MoneroWalletRpc.</span><code><a href="../../wallet/MoneroWalletRpc.html#setDaemonConnection(monero.common.MoneroRpcConnection,java.lang.Boolean,monero.common.SslOptions)" class="member-name-link">setDaemonConnection</a><wbr>(<a href="../MoneroRpcConnection.html" title="class in monero.common">MoneroRpcConnection</a>&nbsp;connection,
<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html" title="class or interface in java.lang" class="external-link">Boolean</a>&nbsp;isTrusted,
<a href="../SslOptions.html" title="class in monero.common">SslOptions</a>&nbsp;sslOptions)</code></div>
<div class="col-last even-row-color">&nbsp;</div>
<div class="col-last even-row-color">
<div class="block">Explicit SSL options take precedence over the connection's verification setting.</div>
</div>
</div>
<div class="caption"><span>Constructors in <a href="../../wallet/package-summary.html">monero.wallet</a> with parameters of type <a href="../MoneroRpcConnection.html" title="class in monero.common">MoneroRpcConnection</a></span></div>
<div class="summary-table three-column-summary">
Expand Down
4 changes: 3 additions & 1 deletion docs/javadocs/monero/common/class-use/SslOptions.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ <h2>Uses of <a href="../SslOptions.html" title="class in monero.common">SslOptio
<div class="col-second even-row-color"><span class="type-name-label">MoneroWalletRpc.</span><code><a href="../../wallet/MoneroWalletRpc.html#setDaemonConnection(monero.common.MoneroRpcConnection,java.lang.Boolean,monero.common.SslOptions)" class="member-name-link">setDaemonConnection</a><wbr>(<a href="../MoneroRpcConnection.html" title="class in monero.common">MoneroRpcConnection</a>&nbsp;connection,
<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html" title="class or interface in java.lang" class="external-link">Boolean</a>&nbsp;isTrusted,
<a href="../SslOptions.html" title="class in monero.common">SslOptions</a>&nbsp;sslOptions)</code></div>
<div class="col-last even-row-color">&nbsp;</div>
<div class="col-last even-row-color">
<div class="block">Explicit SSL options take precedence over the connection's verification setting.</div>
</div>
</div>
</section>
</li>
Expand Down
7 changes: 6 additions & 1 deletion docs/javadocs/monero/wallet/MoneroWalletRpc.html
Original file line number Diff line number Diff line change
Expand Up @@ -943,7 +943,9 @@ <h2>Method Summary</h2>
<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#setDaemonConnection(monero.common.MoneroRpcConnection,java.lang.Boolean,monero.common.SslOptions)" class="member-name-link">setDaemonConnection</a><wbr>(<a href="../common/MoneroRpcConnection.html" title="class in monero.common">MoneroRpcConnection</a>&nbsp;connection,
<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html" title="class or interface in java.lang" class="external-link">Boolean</a>&nbsp;isTrusted,
<a href="../common/SslOptions.html" title="class in monero.common">SslOptions</a>&nbsp;sslOptions)</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4">&nbsp;</div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4">
<div class="block">Explicit SSL options take precedence over the connection's verification setting.</div>
</div>
<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>void</code></div>
<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#setSubaddressLabel(int,int,java.lang.String)" class="member-name-link">setSubaddressLabel</a><wbr>(int&nbsp;accountIdx,
int&nbsp;subaddressIdx,
Expand Down Expand Up @@ -1425,6 +1427,9 @@ <h3>setDaemonConnection</h3>
<div class="member-signature"><span class="modifiers">public</span>&nbsp;<span class="return-type">void</span>&nbsp;<span class="element-name">setDaemonConnection</span><wbr><span class="parameters">(<a href="../common/MoneroRpcConnection.html" title="class in monero.common">MoneroRpcConnection</a>&nbsp;connection,
<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html" title="class or interface in java.lang" class="external-link">Boolean</a>&nbsp;isTrusted,
<a href="../common/SslOptions.html" title="class in monero.common">SslOptions</a>&nbsp;sslOptions)</span></div>
<div class="block">Explicit SSL options take precedence over the connection's verification setting.
The cached connection records the requested allow-any-cert setting, not custom SSL options.
Wallet RPC enforces a CA file or fingerprints; otherwise SSL autodetect can accept unverified certificates.</div>
</section>
</li>
<li>
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.woodser</groupId>
<artifactId>monero-java</artifactId>
<version>0.8.58</version>
<version>0.8.59</version>
<name>Monero Java Library</name>
<description>A Java library for using Monero</description>
<url>https://github.com/woodser/monero-java</url>
Expand Down
27 changes: 15 additions & 12 deletions src/main/cpp/monero_jni_bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ void rethrow_java_exception_as_cpp_exception(JNIEnv* env, jthrowable jexception)
throw runtime_error(msg);
}

void set_daemon_connection(JNIEnv *env, monero_wallet* wallet, jstring juri, jstring jusername, jstring jpassword, jstring jproxy_uri, jint jis_trusted) {
void set_daemon_connection(JNIEnv *env, monero_wallet* wallet, jstring juri, jstring jusername, jstring jpassword, jstring jproxy_uri, jint jis_trusted, jboolean jssl_verify) {

// collect and release string params
const char* _uri = juri ? env->GetStringUTFChars(juri, NULL) : nullptr;
Expand All @@ -116,7 +116,9 @@ void set_daemon_connection(JNIEnv *env, monero_wallet* wallet, jstring juri, jst

// set daemon connection
try {
wallet->set_daemon_connection(uri, username, password, proxy_uri, is_trusted);
auto connection = std::make_shared<monero_rpc_connection>(uri, username, password, proxy_uri);
connection->m_ssl_verify = jssl_verify;
wallet->set_daemon_connection(connection, is_trusted);
} catch (...) {
rethrow_cpp_exception_as_java_exception(env);
}
Expand Down Expand Up @@ -507,8 +509,8 @@ JNIEXPORT jlong JNICALL Java_monero_wallet_MoneroWalletFull_openWalletDataJni(JN
}
}

JNIEXPORT jlong JNICALL Java_monero_wallet_MoneroWalletFull_createWalletJni(JNIEnv *env, jclass clazz, jstring jconfig) {
MTRACE("Java_monero_wallet_MoneroWalletFull_createWalletJni");
JNIEXPORT jlong JNICALL Java_monero_wallet_MoneroWalletFull_createWalletWithSslJni(JNIEnv *env, jclass clazz, jstring jconfig) {
MTRACE("Java_monero_wallet_MoneroWalletFull_createWalletWithSslJni");

// get config as json string
const char* _config = jconfig ? env->GetStringUTFChars(jconfig, NULL) : nullptr;
Expand Down Expand Up @@ -556,11 +558,11 @@ JNIEXPORT jboolean JNICALL Java_monero_wallet_MoneroWalletFull_isViewOnlyJni(JNI
return wallet->is_view_only();
}

JNIEXPORT void JNICALL Java_monero_wallet_MoneroWalletFull_setDaemonConnectionJni(JNIEnv *env, jobject instance, jstring juri, jstring jusername, jstring jpassword, jstring jproxy_uri, jint jis_trusted) {
MTRACE("Java_monero_wallet_MoneroWalletFull_setDaemonConnectionJni");
JNIEXPORT void JNICALL Java_monero_wallet_MoneroWalletFull_setDaemonConnectionWithSslJni(JNIEnv *env, jobject instance, jstring juri, jstring jusername, jstring jpassword, jstring jproxy_uri, jint jis_trusted, jboolean jssl_verify) {
MTRACE("Java_monero_wallet_MoneroWalletFull_setDaemonConnectionWithSslJni");
monero_wallet* wallet = get_handle<monero_wallet>(env, instance, JNI_WALLET_HANDLE);
try {
set_daemon_connection(env, wallet, juri, jusername, jpassword, jproxy_uri, jis_trusted);
set_daemon_connection(env, wallet, juri, jusername, jpassword, jproxy_uri, jis_trusted, jssl_verify);
} catch (...) {
rethrow_cpp_exception_as_java_exception(env);
}
Expand All @@ -577,8 +579,8 @@ JNIEXPORT jboolean JNICALL Java_monero_wallet_MoneroWalletFull_isDaemonTrustedJn
}
}

JNIEXPORT jobjectArray JNICALL Java_monero_wallet_MoneroWalletFull_getDaemonConnectionJni(JNIEnv *env, jobject instance) {
MTRACE("Java_monero_wallet_MoneroWalletFull_getDaemonConnectionJni()");
JNIEXPORT jobjectArray JNICALL Java_monero_wallet_MoneroWalletFull_getDaemonConnectionWithSslJni(JNIEnv *env, jobject instance) {
MTRACE("Java_monero_wallet_MoneroWalletFull_getDaemonConnectionWithSslJni()");

// get wallet
monero_wallet* wallet = get_handle<monero_wallet>(env, instance, JNI_WALLET_HANDLE);
Expand All @@ -588,12 +590,13 @@ JNIEXPORT jobjectArray JNICALL Java_monero_wallet_MoneroWalletFull_getDaemonConn
std::shared_ptr<monero_rpc_connection> daemon_connection = wallet->get_daemon_connection();
if (daemon_connection == nullptr) return 0;

// return string[uri, username, password]
jobjectArray vals = env->NewObjectArray(3, env->FindClass("java/lang/String"), nullptr);
// return string[uri, username, password, proxy_uri, ssl_verify]
jobjectArray vals = env->NewObjectArray(5, env->FindClass("java/lang/String"), nullptr);
if (daemon_connection->m_uri != boost::none && !daemon_connection->m_uri.get().empty()) env->SetObjectArrayElement(vals, 0, env->NewStringUTF(daemon_connection->m_uri.get().c_str()));
if (daemon_connection->m_username != boost::none && !daemon_connection->m_username.get().empty()) env->SetObjectArrayElement(vals, 1, env->NewStringUTF(daemon_connection->m_username.get().c_str()));
if (daemon_connection->m_password != boost::none && !daemon_connection->m_password.get().empty()) env->SetObjectArrayElement(vals, 2, env->NewStringUTF(daemon_connection->m_password.get().c_str()));
if (daemon_connection->m_proxy_uri != boost::none && !daemon_connection->m_proxy_uri.get().empty()) env->SetObjectArrayElement(vals, 2, env->NewStringUTF(daemon_connection->m_proxy_uri.get().c_str()));
if (daemon_connection->m_proxy_uri != boost::none && !daemon_connection->m_proxy_uri.get().empty()) env->SetObjectArrayElement(vals, 3, env->NewStringUTF(daemon_connection->m_proxy_uri.get().c_str()));
env->SetObjectArrayElement(vals, 4, env->NewStringUTF(daemon_connection->m_ssl_verify ? "true" : "false"));
return vals;
} catch (...) {
rethrow_cpp_exception_as_java_exception(env);
Expand Down
6 changes: 3 additions & 3 deletions src/main/cpp/monero_jni_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,17 @@ JNIEXPORT jlong JNICALL Java_monero_wallet_MoneroWalletFull_openWalletJni(JNIEnv

JNIEXPORT jlong JNICALL Java_monero_wallet_MoneroWalletFull_openWalletDataJni(JNIEnv *, jclass, jstring, jint, jbyteArray, jbyteArray, jboolean);

JNIEXPORT jlong JNICALL Java_monero_wallet_MoneroWalletFull_createWalletJni(JNIEnv *, jclass, jstring);
JNIEXPORT jlong JNICALL Java_monero_wallet_MoneroWalletFull_createWalletWithSslJni(JNIEnv *, jclass, jstring);

JNIEXPORT jobjectArray JNICALL Java_monero_wallet_MoneroWalletFull_getSeedLanguagesJni(JNIEnv *, jclass);

// ----------------------------- INSTANCE METHODS -----------------------------

JNIEXPORT jboolean JNICALL Java_monero_wallet_MoneroWalletFull_isViewOnlyJni(JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_monero_wallet_MoneroWalletFull_setDaemonConnectionJni(JNIEnv *, jobject, jstring, jstring, jstring, jstring, jint);
JNIEXPORT void JNICALL Java_monero_wallet_MoneroWalletFull_setDaemonConnectionWithSslJni(JNIEnv *, jobject, jstring, jstring, jstring, jstring, jint, jboolean);

JNIEXPORT jobjectArray JNICALL Java_monero_wallet_MoneroWalletFull_getDaemonConnectionJni(JNIEnv *, jobject);
JNIEXPORT jobjectArray JNICALL Java_monero_wallet_MoneroWalletFull_getDaemonConnectionWithSslJni(JNIEnv *, jobject);

JNIEXPORT jboolean JNICALL Java_monero_wallet_MoneroWalletFull_isConnectedToDaemonJni(JNIEnv *, jobject);

Expand Down
19 changes: 11 additions & 8 deletions src/main/java/monero/common/MoneroConnectionManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public class MoneroConnectionManager {
private boolean autoSwitch = DEFAULT_AUTO_SWITCH;
private long timeoutMs = DEFAULT_TIMEOUT;
private TaskLooper poller;
private Map<MoneroRpcConnection, List<Long>> responseTimes = new HashMap<MoneroRpcConnection, List<Long>>();
private Map<String, List<Long>> responseTimes = new HashMap<String, List<Long>>(); // keyed by uri since connection hashes can change

/**
* Specify behavior when polling.
Expand Down Expand Up @@ -175,7 +175,7 @@ public MoneroConnectionManager removeConnection(String uri) {
MoneroRpcConnection connection = getConnectionByUri(uri);
if (connection == null) throw new MoneroError("No connection exists with URI: " + uri);
connections.remove(connection);
responseTimes.remove(connection);
responseTimes.remove(connection.getUri());
if (connection == currentConnection) {
currentConnection = null;
onConnectionChanged(currentConnection);
Expand Down Expand Up @@ -637,13 +637,16 @@ private boolean checkConnections(Collection<MoneroRpcConnection> connections, Co
private MoneroRpcConnection processResponses(Collection<MoneroRpcConnection> responses) {

// add new connections
Map<String, MoneroRpcConnection> responsesByUri = new HashMap<String, MoneroRpcConnection>();
for (MoneroRpcConnection connection : responses) {
if (!responseTimes.containsKey(connection)) responseTimes.put(connection, new ArrayList<Long>());
responsesByUri.put(connection.getUri(), connection);
if (!responseTimes.containsKey(connection.getUri())) responseTimes.put(connection.getUri(), new ArrayList<Long>());
}

// insert response times or null
for (Entry<MoneroRpcConnection, List<Long>> responseTime : responseTimes.entrySet()) {
responseTime.getValue().add(0, responses.contains(responseTime.getKey()) ? responseTime.getKey().getResponseTime() : null);
for (Entry<String, List<Long>> responseTime : responseTimes.entrySet()) {
MoneroRpcConnection response = responsesByUri.get(responseTime.getKey());
responseTime.getValue().add(0, response == null ? null : response.getResponseTime());

// remove old response times
if (responseTime.getValue().size() > MIN_BETTER_RESPONSES) responseTime.getValue().remove(responseTime.getValue().size() - 1);
Expand Down Expand Up @@ -690,15 +693,15 @@ private MoneroRpcConnection getBestConnectionFromPrioritizedResponses(Collection
if (priorityComparator.compare(bestResponse.getPriority(), bestConnection.getPriority()) != 0) return bestResponse;

// keep best connection if not enough data
if (!responseTimes.containsKey(bestConnection)) return bestConnection;
if (!responseTimes.containsKey(bestConnection.getUri()) || responseTimes.get(bestConnection.getUri()).size() < MIN_BETTER_RESPONSES) return bestConnection;

// check if a connection is consistently better
for (MoneroRpcConnection connection : responses) {
if (connection == bestConnection) continue;
if (!responseTimes.containsKey(connection) || responseTimes.get(connection).size() < MIN_BETTER_RESPONSES) continue;
if (!responseTimes.containsKey(connection.getUri()) || responseTimes.get(connection.getUri()).size() < MIN_BETTER_RESPONSES) continue;
boolean better = true;
for (int i = 0; i < MIN_BETTER_RESPONSES; i++) {
if (responseTimes.get(connection).get(i) == null || responseTimes.get(bestConnection).get(i) == null || responseTimes.get(connection).get(i) > responseTimes.get(bestConnection).get(i)) {
if (responseTimes.get(connection.getUri()).get(i) == null || responseTimes.get(bestConnection.getUri()).get(i) == null || responseTimes.get(connection.getUri()).get(i) > responseTimes.get(bestConnection.getUri()).get(i)) {
better = false;
break;
}
Expand Down
Loading
Loading