diff --git a/README.md b/README.md
index b2bd7d7e..3fa0ae84 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Monero Java Library
-A Java library for creating Monero applications using RPC or JNI bindings to [monero v0.18.5.3 'Fluorine Fermi'](https://github.com/monero-project/monero/tree/v0.18.5.3).
+A Java library for creating Monero applications using RPC or JNI bindings to [monero v0.18.5.4 'Fluorine Fermi'](https://github.com/monero-project/monero/tree/v0.18.5.4).
* Supports wallet and daemon RPC clients.
* Supports client-side wallets using JNI bindings.
@@ -97,7 +97,7 @@ walletFull.close(true);
#### For Gradle, add to build.gradle:
-`compile 'io.github.woodser:monero-java:0.8.63'`
+`compile 'io.github.woodser:monero-java:0.8.64'`
#### For Maven, add to pom.xml:
@@ -105,7 +105,7 @@ walletFull.close(true);
io.github.woodser
monero-java
- 0.8.63
+ 0.8.64
```
diff --git a/docs/monero-spec.drawio b/docs/monero-spec.drawio
index be4d34b6..1416c6b3 100644
--- a/docs/monero-spec.drawio
+++ b/docs/monero-spec.drawio
@@ -1,6 +1,6 @@
-
+
@@ -1901,7 +1901,7 @@
-
+
@@ -2074,7 +2074,7 @@
-
+
diff --git a/docs/monero-spec.pdf b/docs/monero-spec.pdf
index adaa27f4..f937f976 100644
Binary files a/docs/monero-spec.pdf and b/docs/monero-spec.pdf differ
diff --git a/external/monero-cpp b/external/monero-cpp
index 1674b581..65e5356a 160000
--- a/external/monero-cpp
+++ b/external/monero-cpp
@@ -1 +1 @@
-Subproject commit 1674b581ebb6e88a8b2f1d0206d420d51402c978
+Subproject commit 65e5356a9bb8ae487b3feba79f8c07624a5c76d0
diff --git a/pom.xml b/pom.xml
index 1f92cfb5..66a61650 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
io.github.woodser
monero-java
- 0.8.63
+ 0.8.64
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 5057e428..945cb137 100644
--- a/src/main/cpp/monero_jni_bridge.cpp
+++ b/src/main/cpp/monero_jni_bridge.cpp
@@ -1789,7 +1789,7 @@ JNIEXPORT void JNICALL Java_monero_wallet_MoneroWalletFull_setTxNotesJni(JNIEnv*
jstring jstr = (jstring) env->GetObjectArrayElement(jtx_notes, idx);
const char* _str = jstr ? env->GetStringUTFChars(jstr, NULL) : nullptr;
string str = string(_str ? _str : "");
- env->ReleaseStringUTFChars(jstr, _str);
+ if (_str) env->ReleaseStringUTFChars(jstr, _str);
env->DeleteLocalRef(jstr);
notes.push_back(str);
}
diff --git a/src/main/java/monero/common/MoneroUtils.java b/src/main/java/monero/common/MoneroUtils.java
index 4fe2901f..0e511888 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.63";
+ return "0.8.64";
}
/**
diff --git a/src/main/java/monero/wallet/MoneroWalletRpc.java b/src/main/java/monero/wallet/MoneroWalletRpc.java
index c2dc4979..7d028032 100644
--- a/src/main/java/monero/wallet/MoneroWalletRpc.java
+++ b/src/main/java/monero/wallet/MoneroWalletRpc.java
@@ -1668,9 +1668,11 @@ public List getTxNotes(List txHashes) {
@Override
public void setTxNotes(List txHashes, List notes) {
+ List rpcNotes = new ArrayList();
+ for (String note : notes) rpcNotes.add(note == null ? "" : note); // wallet rpc rejects json null; the full wallet clears the note
Map params = new HashMap();
params.put("txids", txHashes);
- params.put("notes", notes);
+ params.put("notes", rpcNotes);
rpc.sendJsonRequest("set_tx_notes", params);
}
diff --git a/src/test/java/TestMoneroWalletCommon.java b/src/test/java/TestMoneroWalletCommon.java
index 57981436..81e323d9 100644
--- a/src/test/java/TestMoneroWalletCommon.java
+++ b/src/test/java/TestMoneroWalletCommon.java
@@ -2238,20 +2238,18 @@ public void testCheckSpendProof() {
@Test
public void testGetReserveProofWallet() {
assumeTrue(TEST_NON_RELAYS);
-
+ TestUtils.WALLET_TX_TRACKER.waitForTxsToClearWallets(wallet); // proof excludes unconfirmed change and incoming funds
+
// get proof of entire wallet
String signature = wallet.getReserveProofWallet("Test message");
-
+
// check proof of entire wallet
MoneroCheckReserve check = wallet.checkReserveProof(wallet.getPrimaryAddress(), "Test message", signature);
assertTrue(check.isGood());
testCheckReserve(check);
- BigInteger balance = wallet.getBalance();
- if (!balance.equals(check.getTotalAmount())) { // TODO monero-wallet-rpc: this check fails with unconfirmed txs
- List unconfirmedTxs = wallet.getTxs(new MoneroTxQuery().setInTxPool(true));
- assertTrue(unconfirmedTxs.size() > 0, "Reserve amount must equal balance unless wallet has unconfirmed txs");
- }
-
+ BigInteger reserve = check.getTotalAmount().subtract(check.getUnconfirmedSpentAmount()); // TODO monero-project: compare total directly once failed txs stop unspending confirmed inputs
+ assertEquals(wallet.getBalance(), reserve);
+
// test different wallet address
String differentAddress = TestUtils.getExternalWalletAddress();
try {
@@ -2376,6 +2374,10 @@ public void testSetTxNote() {
for (int i = 0; i < txs.size(); i++) {
assertEquals(wallet.getTxNote(txs.get(i).getHash()), uuid + i);
}
+
+ // null clears the note
+ wallet.setTxNote(txs.get(0).getHash(), null);
+ assertEquals("", wallet.getTxNote(txs.get(0).getHash()));
}
// Can get and set multiple transaction notes
@@ -2390,7 +2392,7 @@ public void testSetTxNotes() {
assertTrue(txs.size() >= 3, "Test requires 3 or more wallet transactions; run send tests");
List txHashes = new ArrayList();
List txNotes = new ArrayList();
- for (int i = 0; i < txHashes.size(); i++) {
+ for (int i = 0; i < txs.size(); i++) {
txHashes.add(txs.get(i).getHash());
txNotes.add(uuid + i);
}
@@ -2402,6 +2404,16 @@ public void testSetTxNotes() {
assertEquals(uuid + i, txNotes.get(i));
}
+ // clear notes in a mixed batch without changing the caller's list
+ txNotes.set(0, null);
+ txNotes.set(1, "");
+ txNotes.set(2, "null");
+ List expectedNotes = new ArrayList(txNotes);
+ expectedNotes.set(0, "");
+ wallet.setTxNotes(txHashes, Collections.unmodifiableList(txNotes));
+ assertNull(txNotes.get(0));
+ assertEquals(expectedNotes, wallet.getTxNotes(txHashes));
+
// TODO: test that get transaction has note
}
diff --git a/src/test/java/TestMoneroWalletFull.java b/src/test/java/TestMoneroWalletFull.java
index 9ca2f508..a5158ebd 100644
--- a/src/test/java/TestMoneroWalletFull.java
+++ b/src/test/java/TestMoneroWalletFull.java
@@ -1397,6 +1397,7 @@ private class WalletSyncTester extends SyncProgressTester {
private BigInteger incomingTotal;
private BigInteger outgoingTotal;
private Boolean onNewBlockAfterDone;
+ private boolean testedTxNote;
private BigInteger prevBalance;
private BigInteger prevUnlockedBalance;
@@ -1446,6 +1447,17 @@ public void onOutputReceived(MoneroOutputWallet output) {
assertNull(output.getTx().getInputs());
assertEquals(1, output.getTx().getOutputs().size());
assertTrue(output.getTx().getOutputs().get(0) == output);
+
+ // can read and write tx notes from a sync callback
+ String txHash = output.getTx().getHash();
+ String previousNote = wallet.getTxNote(txHash);
+ try {
+ wallet.setTxNote(txHash, "sync callback");
+ assertEquals("sync callback", wallet.getTxNote(txHash));
+ testedTxNote = true;
+ } finally {
+ wallet.setTxNote(txHash, previousNote);
+ }
// extra is not sent over the jni bridge
assertNull(output.getTx().getExtra());
@@ -1487,6 +1499,7 @@ public void onDone(long chainHeight) {
assertNotNull(walletTesterPrevHeight);
assertNotNull(prevOutputReceived);
assertNotNull(prevOutputSpent);
+ assertTrue(testedTxNote);
BigInteger expectedBalance = incomingTotal.subtract(outgoingTotal);
// output notifications do not include pool fees or outgoing amount