diff --git a/README.md b/README.md
index c076744f..391493eb 100644
--- a/README.md
+++ b/README.md
@@ -97,7 +97,7 @@ walletFull.close(true);
#### For Gradle, add to build.gradle:
-`compile 'io.github.woodser:monero-java:0.8.55'`
+`compile 'io.github.woodser:monero-java:0.8.56'`
#### For Maven, add to pom.xml:
@@ -105,7 +105,7 @@ walletFull.close(true);
io.github.woodser
monero-java
- 0.8.55
+ 0.8.56
```
diff --git a/external/monero-cpp b/external/monero-cpp
index 8db4afab..6927f7bf 160000
--- a/external/monero-cpp
+++ b/external/monero-cpp
@@ -1 +1 @@
-Subproject commit 8db4afab28f394f3dc78de6b4c2d3473484ce1b9
+Subproject commit 6927f7bf52dabad2179dfe2a0a0e1a95e12290c1
diff --git a/pom.xml b/pom.xml
index 51a31d74..387b765a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
io.github.woodser
monero-java
- 0.8.55
+ 0.8.56
Monero Java Library
A Java library for using Monero
https://github.com/woodser/monero-java
diff --git a/src/main/cpp/monero_jni_bridge.cpp b/src/main/cpp/monero_jni_bridge.cpp
index d7d22623..a2bed5a1 100644
--- a/src/main/cpp/monero_jni_bridge.cpp
+++ b/src/main/cpp/monero_jni_bridge.cpp
@@ -1428,10 +1428,10 @@ JNIEXPORT jstring JNICALL Java_monero_wallet_MoneroWalletFull_describeTxSetJni(J
try {
// deserialize tx set to describe
- monero_tx_set tx_set = monero_tx_set::deserialize(tx_set_json);
+ shared_ptr tx_set = monero_tx_set::deserialize(tx_set_json);
// describe tx set
- monero_tx_set described_tx_set = wallet->describe_tx_set(tx_set);
+ monero_tx_set described_tx_set = wallet->describe_tx_set(*tx_set);
// serialize, free, and return
std::string monero_tx_set_json = described_tx_set.serialize();
diff --git a/src/main/java/monero/common/MoneroUtils.java b/src/main/java/monero/common/MoneroUtils.java
index ad397f0c..e8593ac5 100644
--- a/src/main/java/monero/common/MoneroUtils.java
+++ b/src/main/java/monero/common/MoneroUtils.java
@@ -42,7 +42,7 @@ public class MoneroUtils {
* @return the version of this monero-java library
*/
public static String getVersion() {
- return "0.8.55";
+ return "0.8.56";
}
/**
diff --git a/src/main/java/monero/common/TaskLooper.java b/src/main/java/monero/common/TaskLooper.java
index 0afd82f8..a2d24c3a 100644
--- a/src/main/java/monero/common/TaskLooper.java
+++ b/src/main/java/monero/common/TaskLooper.java
@@ -54,15 +54,23 @@ public synchronized TaskLooper start(long periodInMs, boolean targetFixedPeriod)
if (isStarted) return this;
isStarted = true;
- // start looping
+ // reuse a live loop, which observes isStarted under lock and continues
if (isLooping) return this;
isLooping = true;
TaskLooper that = this;
Thread loop = new Thread(new Runnable() {
@Override
public void run() {
- while (isStarted && !Thread.currentThread().isInterrupted()) {
-
+ while (true) {
+
+ // decide to exit and clear isLooping atomically so a restart cannot reuse a dead loop
+ synchronized (that) {
+ if (!isStarted || Thread.currentThread().isInterrupted()) {
+ isLooping = false;
+ return;
+ }
+ }
+
// run the task
long startTime = System.currentTimeMillis();
task.run();
@@ -71,12 +79,12 @@ public void run() {
if (isStarted) {
try { TimeUnit.MILLISECONDS.sleep(that.periodInMs - (targetFixedPeriod ? System.currentTimeMillis() - startTime : 0)); } // target fixed period by accounting for run time
catch (Exception e) {
- isLooping = false;
+ synchronized (that) { isLooping = false; }
if (isStarted) throw new RuntimeException(e);
+ return;
}
}
}
- isLooping = false;
}
});
loop.start();
diff --git a/src/main/java/monero/wallet/MoneroWalletRpc.java b/src/main/java/monero/wallet/MoneroWalletRpc.java
index 26e87934..cb6b2604 100644
--- a/src/main/java/monero/wallet/MoneroWalletRpc.java
+++ b/src/main/java/monero/wallet/MoneroWalletRpc.java
@@ -2421,8 +2421,14 @@ public void poll() {
// announce new unlocked outputs
for (MoneroTxWallet unlockedTx : unlockedTxs) {
+ boolean missedConfirm = Boolean.TRUE.equals(unlockedTx.isConfirmed()) && !prevConfirmedNotifications.contains(unlockedTx.getHash());
prevUnconfirmedNotifications.remove(unlockedTx.getHash()); // stop tracking tx notifications
prevConfirmedNotifications.remove(unlockedTx.getHash());
+ if (missedConfirm) { // announce missed confirm transition if tx unlocked between polls
+ MoneroTxWallet confirmedTx = unlockedTx.copy().setIsLocked(true);
+ confirmedTx.setBlock(unlockedTx.getBlock().copy().setTxs(confirmedTx));
+ notifyOutputs(confirmedTx);
+ }
notifyOutputs(unlockedTx);
}
diff --git a/src/test/java/TestMoneroWalletFull.java b/src/test/java/TestMoneroWalletFull.java
index 4275b2ba..8c77fc2a 100644
--- a/src/test/java/TestMoneroWalletFull.java
+++ b/src/test/java/TestMoneroWalletFull.java
@@ -251,8 +251,9 @@ public void testCreateWalletRandomFull() {
// cannot get daemon chain height
try {
wallet.getDaemonHeight();
+ fail("Should have thrown exception");
} catch (MoneroError e) {
- assertEquals("Wallet is not connected to daemon", e.getMessage());
+ assertEquals("daemon error", e.getMessage()); // wallet2 masks errors from untrusted daemons
}
// set daemon connection and check chain height
@@ -307,7 +308,7 @@ public void testCreateWalletFromSeedFull() {
assertFalse(wallet.isSynced());
assertEquals(1, wallet.getHeight());
assertEquals(0, wallet.getRestoreHeight());
- try { wallet.startSyncing(); } catch (MoneroError e) { assertEquals("Wallet is not connected to daemon", e.getMessage()); }
+ wallet.startSyncing(); // succeeds while offline, syncing when a daemon becomes reachable
wallet.close();
// create wallet without restore height
@@ -771,9 +772,7 @@ public void testStartStopSyncing() {
assertNotNull(wallet.getSeed());
assertEquals(1, wallet.getHeight());
assertEquals(BigInteger.valueOf(0), wallet.getBalance());
- wallet.startSyncing();
- } catch (MoneroError e) {
- assertEquals("Wallet is not connected to daemon", e.getMessage());
+ wallet.startSyncing(); // succeeds while offline, syncing when a daemon becomes reachable
} finally {
wallet.close();
}