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