From fd4fe67e243e86bd52eea17f9b394fbf27fe0e41 Mon Sep 17 00:00:00 2001 From: Sean Gilligan Date: Wed, 24 Dec 2025 10:18:33 -0800 Subject: [PATCH 1/5] module-info.java: add transitive dependencies for bitcoinj-core to wallettemplate Add transitive dependencies of bitcoinj-core that are not strictly needed for the build, but prevent errors or warnings in IDEs. These lines can be removed when bitcoinj-core gets a module-info. --- wallettemplate/src/main/java/module-info.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wallettemplate/src/main/java/module-info.java b/wallettemplate/src/main/java/module-info.java index 3bc6d48aa76..f478785059e 100644 --- a/wallettemplate/src/main/java/module-info.java +++ b/wallettemplate/src/main/java/module-info.java @@ -27,6 +27,11 @@ requires com.google.zxing; requires org.bitcoinj.core; + // Since bitcoinj-core doesn't have a module-info and IDEs are generally unaware of the + // processing done by the jlink plugin, we include transitive dependencies here that would + // be unnecessary if bitcoinj-core were fully modular. + requires org.bitcoinj.base; // Transitive via bitcoinj-core + requires com.google.protobuf; // Transitive via bitcoinj-core exports wallettemplate; exports org.bitcoinj.walletfx.controls; From d44d1008f856b9c4e709eb95ccf1a63c4a63a698 Mon Sep 17 00:00:00 2001 From: nadavramon <159230565+nadavramon@users.noreply.github.com> Date: Fri, 9 Jan 2026 16:33:22 +0200 Subject: [PATCH 2/5] AbstractFullPrunedBlockChainTest: replace usage of Guava `Lists.newArrayList()` with JDK `Arrays.asList()` --- .../org/bitcoinj/core/AbstractFullPrunedBlockChainTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/test/java/org/bitcoinj/core/AbstractFullPrunedBlockChainTest.java b/core/src/test/java/org/bitcoinj/core/AbstractFullPrunedBlockChainTest.java index 4b3b974677c..084f4318859 100644 --- a/core/src/test/java/org/bitcoinj/core/AbstractFullPrunedBlockChainTest.java +++ b/core/src/test/java/org/bitcoinj/core/AbstractFullPrunedBlockChainTest.java @@ -17,7 +17,7 @@ package org.bitcoinj.core; -import com.google.common.collect.Lists; + import org.bitcoinj.base.Address; import org.bitcoinj.base.BitcoinNetwork; import org.bitcoinj.base.Coin; @@ -298,7 +298,7 @@ public void testGetOpenTransactionOutputs() throws Exception { chain.add(rollingBlock); totalAmount = totalAmount.add(amount); - List outputs = store.getOpenTransactionOutputs(Lists.newArrayList(toKey)); + List outputs = store.getOpenTransactionOutputs(Arrays.asList(toKey)); assertNotNull(outputs); assertEquals("Wrong Number of Outputs", 1, outputs.size()); UTXO output = outputs.get(0); From a683c0f35157aa52b3164fd6cbbfe886dc99e09c Mon Sep 17 00:00:00 2001 From: nadavramon <159230565+nadavramon@users.noreply.github.com> Date: Fri, 9 Jan 2026 17:38:57 +0200 Subject: [PATCH 3/5] ScriptOpCodes: replace Guava `ImmutableBiMap` with JDK `Collections.unmodifiableMap()` --- .../org/bitcoinj/script/ScriptOpCodes.java | 237 +++++++++--------- 1 file changed, 121 insertions(+), 116 deletions(-) diff --git a/core/src/main/java/org/bitcoinj/script/ScriptOpCodes.java b/core/src/main/java/org/bitcoinj/script/ScriptOpCodes.java index 7e9d4166f78..a8a73c5cab8 100644 --- a/core/src/main/java/org/bitcoinj/script/ScriptOpCodes.java +++ b/core/src/main/java/org/bitcoinj/script/ScriptOpCodes.java @@ -16,9 +16,6 @@ package org.bitcoinj.script; -import com.google.common.collect.BiMap; -import com.google.common.collect.ImmutableBiMap; - import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -167,123 +164,131 @@ public class ScriptOpCodes { public static final int OP_NOP10 = 0xb9; public static final int OP_INVALIDOPCODE = 0xff; - private static final BiMap opCodeMap = ImmutableBiMap.builder() - .put(OP_0, "0") - .put(OP_PUSHDATA1, "PUSHDATA1") - .put(OP_PUSHDATA2, "PUSHDATA2") - .put(OP_PUSHDATA4, "PUSHDATA4") - .put(OP_1NEGATE, "1NEGATE") - .put(OP_RESERVED, "RESERVED") - .put(OP_1, "1") - .put(OP_2, "2") - .put(OP_3, "3") - .put(OP_4, "4") - .put(OP_5, "5") - .put(OP_6, "6") - .put(OP_7, "7") - .put(OP_8, "8") - .put(OP_9, "9") - .put(OP_10, "10") - .put(OP_11, "11") - .put(OP_12, "12") - .put(OP_13, "13") - .put(OP_14, "14") - .put(OP_15, "15") - .put(OP_16, "16") - .put(OP_NOP, "NOP") - .put(OP_VER, "VER") - .put(OP_IF, "IF") - .put(OP_NOTIF, "NOTIF") - .put(OP_VERIF, "VERIF") - .put(OP_VERNOTIF, "VERNOTIF") - .put(OP_ELSE, "ELSE") - .put(OP_ENDIF, "ENDIF") - .put(OP_VERIFY, "VERIFY") - .put(OP_RETURN, "RETURN") - .put(OP_TOALTSTACK, "TOALTSTACK") - .put(OP_FROMALTSTACK, "FROMALTSTACK") - .put(OP_2DROP, "2DROP") - .put(OP_2DUP, "2DUP") - .put(OP_3DUP, "3DUP") - .put(OP_2OVER, "2OVER") - .put(OP_2ROT, "2ROT") - .put(OP_2SWAP, "2SWAP") - .put(OP_IFDUP, "IFDUP") - .put(OP_DEPTH, "DEPTH") - .put(OP_DROP, "DROP") - .put(OP_DUP, "DUP") - .put(OP_NIP, "NIP") - .put(OP_OVER, "OVER") - .put(OP_PICK, "PICK") - .put(OP_ROLL, "ROLL") - .put(OP_ROT, "ROT") - .put(OP_SWAP, "SWAP") - .put(OP_TUCK, "TUCK") - .put(OP_CAT, "CAT") - .put(OP_SUBSTR, "SUBSTR") - .put(OP_LEFT, "LEFT") - .put(OP_RIGHT, "RIGHT") - .put(OP_SIZE, "SIZE") - .put(OP_INVERT, "INVERT") - .put(OP_AND, "AND") - .put(OP_OR, "OR") - .put(OP_XOR, "XOR") - .put(OP_EQUAL, "EQUAL") - .put(OP_EQUALVERIFY, "EQUALVERIFY") - .put(OP_RESERVED1, "RESERVED1") - .put(OP_RESERVED2, "RESERVED2") - .put(OP_1ADD, "1ADD") - .put(OP_1SUB, "1SUB") - .put(OP_2MUL, "2MUL") - .put(OP_2DIV, "2DIV") - .put(OP_NEGATE, "NEGATE") - .put(OP_ABS, "ABS") - .put(OP_NOT, "NOT") - .put(OP_0NOTEQUAL, "0NOTEQUAL") - .put(OP_ADD, "ADD") - .put(OP_SUB, "SUB") - .put(OP_MUL, "MUL") - .put(OP_DIV, "DIV") - .put(OP_MOD, "MOD") - .put(OP_LSHIFT, "LSHIFT") - .put(OP_RSHIFT, "RSHIFT") - .put(OP_BOOLAND, "BOOLAND") - .put(OP_BOOLOR, "BOOLOR") - .put(OP_NUMEQUAL, "NUMEQUAL") - .put(OP_NUMEQUALVERIFY, "NUMEQUALVERIFY") - .put(OP_NUMNOTEQUAL, "NUMNOTEQUAL") - .put(OP_LESSTHAN, "LESSTHAN") - .put(OP_GREATERTHAN, "GREATERTHAN") - .put(OP_LESSTHANOREQUAL, "LESSTHANOREQUAL") - .put(OP_GREATERTHANOREQUAL, "GREATERTHANOREQUAL") - .put(OP_MIN, "MIN") - .put(OP_MAX, "MAX") - .put(OP_WITHIN, "WITHIN") - .put(OP_RIPEMD160, "RIPEMD160") - .put(OP_SHA1, "SHA1") - .put(OP_SHA256, "SHA256") - .put(OP_HASH160, "HASH160") - .put(OP_HASH256, "HASH256") - .put(OP_CODESEPARATOR, "CODESEPARATOR") - .put(OP_CHECKSIG, "CHECKSIG") - .put(OP_CHECKSIGVERIFY, "CHECKSIGVERIFY") - .put(OP_CHECKMULTISIG, "CHECKMULTISIG") - .put(OP_CHECKMULTISIGVERIFY, "CHECKMULTISIGVERIFY") - .put(OP_NOP1, "NOP1") - .put(OP_CHECKLOCKTIMEVERIFY, "CHECKLOCKTIMEVERIFY") - .put(OP_CHECKSEQUENCEVERIFY, "CHECKSEQUENCEVERIFY") - .put(OP_NOP4, "NOP4") - .put(OP_NOP5, "NOP5") - .put(OP_NOP6, "NOP6") - .put(OP_NOP7, "NOP7") - .put(OP_NOP8, "NOP8") - .put(OP_NOP9, "NOP9") - .put(OP_NOP10, "NOP10").build(); + private static final Map opCodeMap; + static { + Map map = new HashMap<>(); + map.put(OP_0, "0"); + map.put(OP_PUSHDATA1, "PUSHDATA1"); + map.put(OP_PUSHDATA2, "PUSHDATA2"); + map.put(OP_PUSHDATA4, "PUSHDATA4"); + map.put(OP_1NEGATE, "1NEGATE"); + map.put(OP_RESERVED, "RESERVED"); + map.put(OP_1, "1"); + map.put(OP_2, "2"); + map.put(OP_3, "3"); + map.put(OP_4, "4"); + map.put(OP_5, "5"); + map.put(OP_6, "6"); + map.put(OP_7, "7"); + map.put(OP_8, "8"); + map.put(OP_9, "9"); + map.put(OP_10, "10"); + map.put(OP_11, "11"); + map.put(OP_12, "12"); + map.put(OP_13, "13"); + map.put(OP_14, "14"); + map.put(OP_15, "15"); + map.put(OP_16, "16"); + map.put(OP_NOP, "NOP"); + map.put(OP_VER, "VER"); + map.put(OP_IF, "IF"); + map.put(OP_NOTIF, "NOTIF"); + map.put(OP_VERIF, "VERIF"); + map.put(OP_VERNOTIF, "VERNOTIF"); + map.put(OP_ELSE, "ELSE"); + map.put(OP_ENDIF, "ENDIF"); + map.put(OP_VERIFY, "VERIFY"); + map.put(OP_RETURN, "RETURN"); + map.put(OP_TOALTSTACK, "TOALTSTACK"); + map.put(OP_FROMALTSTACK, "FROMALTSTACK"); + map.put(OP_2DROP, "2DROP"); + map.put(OP_2DUP, "2DUP"); + map.put(OP_3DUP, "3DUP"); + map.put(OP_2OVER, "2OVER"); + map.put(OP_2ROT, "2ROT"); + map.put(OP_2SWAP, "2SWAP"); + map.put(OP_IFDUP, "IFDUP"); + map.put(OP_DEPTH, "DEPTH"); + map.put(OP_DROP, "DROP"); + map.put(OP_DUP, "DUP"); + map.put(OP_NIP, "NIP"); + map.put(OP_OVER, "OVER"); + map.put(OP_PICK, "PICK"); + map.put(OP_ROLL, "ROLL"); + map.put(OP_ROT, "ROT"); + map.put(OP_SWAP, "SWAP"); + map.put(OP_TUCK, "TUCK"); + map.put(OP_CAT, "CAT"); + map.put(OP_SUBSTR, "SUBSTR"); + map.put(OP_LEFT, "LEFT"); + map.put(OP_RIGHT, "RIGHT"); + map.put(OP_SIZE, "SIZE"); + map.put(OP_INVERT, "INVERT"); + map.put(OP_AND, "AND"); + map.put(OP_OR, "OR"); + map.put(OP_XOR, "XOR"); + map.put(OP_EQUAL, "EQUAL"); + map.put(OP_EQUALVERIFY, "EQUALVERIFY"); + map.put(OP_RESERVED1, "RESERVED1"); + map.put(OP_RESERVED2, "RESERVED2"); + map.put(OP_1ADD, "1ADD"); + map.put(OP_1SUB, "1SUB"); + map.put(OP_2MUL, "2MUL"); + map.put(OP_2DIV, "2DIV"); + map.put(OP_NEGATE, "NEGATE"); + map.put(OP_ABS, "ABS"); + map.put(OP_NOT, "NOT"); + map.put(OP_0NOTEQUAL, "0NOTEQUAL"); + map.put(OP_ADD, "ADD"); + map.put(OP_SUB, "SUB"); + map.put(OP_MUL, "MUL"); + map.put(OP_DIV, "DIV"); + map.put(OP_MOD, "MOD"); + map.put(OP_LSHIFT, "LSHIFT"); + map.put(OP_RSHIFT, "RSHIFT"); + map.put(OP_BOOLAND, "BOOLAND"); + map.put(OP_BOOLOR, "BOOLOR"); + map.put(OP_NUMEQUAL, "NUMEQUAL"); + map.put(OP_NUMEQUALVERIFY, "NUMEQUALVERIFY"); + map.put(OP_NUMNOTEQUAL, "NUMNOTEQUAL"); + map.put(OP_LESSTHAN, "LESSTHAN"); + map.put(OP_GREATERTHAN, "GREATERTHAN"); + map.put(OP_LESSTHANOREQUAL, "LESSTHANOREQUAL"); + map.put(OP_GREATERTHANOREQUAL, "GREATERTHANOREQUAL"); + map.put(OP_MIN, "MIN"); + map.put(OP_MAX, "MAX"); + map.put(OP_WITHIN, "WITHIN"); + map.put(OP_RIPEMD160, "RIPEMD160"); + map.put(OP_SHA1, "SHA1"); + map.put(OP_SHA256, "SHA256"); + map.put(OP_HASH160, "HASH160"); + map.put(OP_HASH256, "HASH256"); + map.put(OP_CODESEPARATOR, "CODESEPARATOR"); + map.put(OP_CHECKSIG, "CHECKSIG"); + map.put(OP_CHECKSIGVERIFY, "CHECKSIGVERIFY"); + map.put(OP_CHECKMULTISIG, "CHECKMULTISIG"); + map.put(OP_CHECKMULTISIGVERIFY, "CHECKMULTISIGVERIFY"); + map.put(OP_NOP1, "NOP1"); + map.put(OP_CHECKLOCKTIMEVERIFY, "CHECKLOCKTIMEVERIFY"); + map.put(OP_CHECKSEQUENCEVERIFY, "CHECKSEQUENCEVERIFY"); + map.put(OP_NOP4, "NOP4"); + map.put(OP_NOP5, "NOP5"); + map.put(OP_NOP6, "NOP6"); + map.put(OP_NOP7, "NOP7"); + map.put(OP_NOP8, "NOP8"); + map.put(OP_NOP9, "NOP9"); + map.put(OP_NOP10, "NOP10"); + opCodeMap = Collections.unmodifiableMap(map); + } private static final Map opCodeNameMap = createOpCodeNameMap(); private static Map createOpCodeNameMap() { - Map map = new HashMap<>(opCodeMap.inverse()); + Map map = new HashMap<>(); + + for (Map.Entry entry : opCodeMap.entrySet()) { + map.put(entry.getValue(), entry.getKey()); + } map.put("OP_FALSE", OP_FALSE); map.put("OP_TRUE", OP_TRUE); map.put("NOP2", OP_NOP2); From 9049961787109cefb0cbcf6a70ce22b071344983 Mon Sep 17 00:00:00 2001 From: nadavramon <159230565+nadavramon@users.noreply.github.com> Date: Mon, 12 Jan 2026 19:17:57 +0200 Subject: [PATCH 4/5] BtcFormat: replace usage of Guava `Strings.isNullOrEmpty()` with private helper --- .../main/java/org/bitcoinj/utils/BtcFormat.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/bitcoinj/utils/BtcFormat.java b/core/src/main/java/org/bitcoinj/utils/BtcFormat.java index 47a30bd504d..45c7be4e7cb 100644 --- a/core/src/main/java/org/bitcoinj/utils/BtcFormat.java +++ b/core/src/main/java/org/bitcoinj/utils/BtcFormat.java @@ -679,7 +679,7 @@ public Builder scale(int val) { *

Note that by applying a pattern you override the configured formatting style of * {@link BtcAutoFormat} instances. */ public Builder pattern(String val) { - if (!Strings.isNullOrEmpty(localizedPattern)) + if (!isNullOrEmpty(localizedPattern)) throw new IllegalStateException("You cannot invoke both pattern() and localizedPattern()"); pattern = val; return this; @@ -713,7 +713,7 @@ public Builder pattern(String val) { *

Note that by applying a pattern you override the configured formatting style of * {@link BtcAutoFormat} instances. */ public Builder localizedPattern(String val) { - if (!Strings.isNullOrEmpty(pattern)) + if (!isNullOrEmpty(pattern)) throw new IllegalStateException("You cannot invoke both pattern() and localizedPattern()."); localizedPattern = val; return this; @@ -723,16 +723,16 @@ public Builder localizedPattern(String val) { * to the state of this {@code Builder} instance at the time this method is invoked. */ public BtcFormat build() { BtcFormat f = variant.newInstance(this); - if (!Strings.isNullOrEmpty(symbol) || !Strings.isNullOrEmpty(code)) { synchronized(f.numberFormat) { + if (!isNullOrEmpty(symbol) || !isNullOrEmpty(code)) { synchronized(f.numberFormat) { DecimalFormatSymbols defaultSigns = f.numberFormat.getDecimalFormatSymbols(); setSymbolAndCode(f.numberFormat, - !Strings.isNullOrEmpty(symbol) ? symbol : defaultSigns.getCurrencySymbol(), - !Strings.isNullOrEmpty(code) ? code : defaultSigns.getInternationalCurrencySymbol() + !isNullOrEmpty(symbol) ? symbol : defaultSigns.getCurrencySymbol(), + !isNullOrEmpty(code) ? code : defaultSigns.getInternationalCurrencySymbol() ); }} - if (!Strings.isNullOrEmpty(localizedPattern) || !Strings.isNullOrEmpty(pattern)) { + if (!isNullOrEmpty(localizedPattern) || !isNullOrEmpty(pattern)) { int places = f.numberFormat.getMinimumFractionDigits(); - if (!Strings.isNullOrEmpty(localizedPattern)) f.numberFormat.applyLocalizedPattern(negify(localizedPattern)); + if (!isNullOrEmpty(localizedPattern)) f.numberFormat.applyLocalizedPattern(negify(localizedPattern)); else f.numberFormat.applyPattern(negify(pattern)); f.numberFormat.setMinimumFractionDigits(places); f.numberFormat.setMaximumFractionDigits(places); @@ -1595,4 +1595,7 @@ public DecimalFormatSymbols symbols() { synchronized(numberFormat) { return Objects.hash(pattern(), symbols(), minimumFractionDigits, decimalGroups); } + private static boolean isNullOrEmpty(String s) { + return s == null || s.isEmpty(); + } } From 1e619c8bc4f2412a504427997f0107092ee12c4c Mon Sep 17 00:00:00 2001 From: nadavramon <159230565+nadavramon@users.noreply.github.com> Date: Mon, 12 Jan 2026 19:18:58 +0200 Subject: [PATCH 5/5] BtcFormat: replace usage of Guava `Strings.repeat()` with JDK `Collections.nCopies()` --- core/src/main/java/org/bitcoinj/utils/BtcFormat.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/java/org/bitcoinj/utils/BtcFormat.java b/core/src/main/java/org/bitcoinj/utils/BtcFormat.java index 45c7be4e7cb..2ae6df33977 100644 --- a/core/src/main/java/org/bitcoinj/utils/BtcFormat.java +++ b/core/src/main/java/org/bitcoinj/utils/BtcFormat.java @@ -16,7 +16,6 @@ package org.bitcoinj.utils; -import com.google.common.base.Strings; import org.bitcoinj.base.Coin; import org.bitcoinj.utils.BtcAutoFormat.Style; @@ -1549,7 +1548,7 @@ public String coinCode() { synchronized(numberFormat) { public String pattern() { synchronized(numberFormat) { StringBuilder groups = new StringBuilder(); for (int group : decimalGroups) { - groups.append("(").append(Strings.repeat("#", group)).append(")"); + groups.append("(").append(String.join("", Collections.nCopies(group, "#"))).append(")"); } DecimalFormatSymbols s = numberFormat.getDecimalFormatSymbols(); String digit = String.valueOf(s.getDigit());